2011-01-09 16 views
39

Mam klasę, która ma słuchać zdarzeń myszy. Nie chcę jednak zmuszać użytkownika do implementacji żadnego konkretnego, ale chcę wyjaśnić, że musi go odziedziczyć.Tworzenie abstrakcji klasy bez żadnych czystych metod wirtualnych

Czy istnieje sposób, aby to zrobić?

Dzięki

+1

Zabawne: Java MouseAdapter to dokładnie to, co planujesz napisać: klasa abstrakcyjna bez żadnych czystych wirtualnych metod, aby ludzie mogli swobodnie wybierać, które metody słuchacza chcą zaimplementować, a które nie. –

+2

Czy rzeczywiście ma znaczenie, jeśli ktoś tworzy instancję klasy podstawowej i rejestruje ją jako nasłuchiwanie myszy? Przypuszczalnie po prostu zignoruje wszystko (lub wykona domyślne akcje dla wszystkiego), dokładnie tak samo, jakby zadał sobie trud napisania kodu, który odziedziczyłby po klasie, ale nie zaimplementował żadnej z tych funkcji. Dwa różne sposoby robienia czegoś bezcelowego zamiast jednego. –

Odpowiedz

47

Możesz zadeklarować czysty wirtualny destruktor, ale nadaj mu definicję. Klasa będzie abstrakcyjna, ale wszelkie klasy dziedziczące nie będą domyślnie abstrakcyjne.

struct Abstract 
{ 
    virtual ~Abstract() = 0; 
}; 

Abstract::~Abstract() {} 

struct Valid: public Abstract 
{ 
     // Notice you don't need to actually overide the base 
     // classes pure virtual method as it has a default 
}; 


int main() 
{ 
    // Abstract  a; // This line fails to compile as Abstract is abstract 
    Valid   v; // This compiles fine. 
} 
+2

Czy możesz dać przykład, próbowałem tego, ale moje podklasy nadal stają się abstrakcyjne. – jmasterx

+0

@Milo http://programmers.stackexchange.com/questions/35038/what-can-i-do-when-the-interviewer-doesnt-now-the-answer-to-his-her-own-questio/35043 # 35043 –

+0

@Philip: Niepoprawnie. Klasa dziedzicząca będzie musiała przedstawić implementację, w przeciwnym razie będą one nadal abstrakcyjne. – AbdullahC

38

Określ konstruktora bazy jako chroniony. Oznacza to, że nie można go zbudować bezpośrednio, ale wymusza dziedziczenie. Nie ma nic, co spowodowałoby, że deweloper odziedziczyłby tę klasę poza dobrą dokumentacją!

1

Dlaczego chcesz, aby użytkownik odziedziczył, jeśli nie musi niczego wdrażać.

Gdy klasa bazowa jest potrzebna, aby móc umieścić wszystkie "sterowniki zdarzeń" w zestawie std :: set. Wtedy nikt nie może stworzyć klasy i umieścić go w tym zestawie bez podklasy twojej klasy bazowej. Ponieważ zestaw będzie zdefiniowany jako

std::set<MyBaseClass*> mySet; 
+1

Być może użytkownik nie dziedziczy, ale dwie odrębne klasy oferujące wyłącznych członków, mając wspólną bazę, mają sens. HttpTransaction-> HttpRequest, HttpTransaction-> HttpResponse, itp. –

3

Możesz zadeklarować, że jesteś klasą podstawową jako posiadającą czysty wirtualny destruktor, który implementujesz. Ponieważ destruktor jest zawsze dostarczany przez kompilator, klasa pochodna nie będzie czysto wirtualna, ale klasa podstawowa nie może być bezpośrednio utworzona. Ponieważ zawsze powinieneś zadeklarować wirtualny destruktor, jeśli twoja klasa ma metodę wirtualną, nie wiąże się to z żadnymi kosztami.

class Base 
{ 
public: 
    virtual ~Base() = 0; 
    virtual void SomeVirtualMethod(); 
}; 

inline Base::~Base() 
{ 
} 

class Derived : public Base 
{ 
}; 

inline Base* createBase() 
{ 
    // return new Base; // <- This won't compile 
    return new Derived; // <- This compile, Derived is not a pure virtual class ! 
} 
1

Z definicji klasa abstrakcyjna jest klasą, która ma co najmniej jedną czystą funkcję wirtualną. Dla Państwa celów, można zdefiniować destruktora być czysto wirtualne i zapewnienie realizacji:

class abstract { 
     virtual ~abstract()=0; 
}; 

abstract::~abstract() {} 

Domyślnie wszystkie klasy dziedziczące nie będzie abstrakcyjny, choć nie będą one potrzebne do realizacji dowolnej metody.

Powiązane problemy