2013-01-31 13 views
13

Mam klasy bazowejKlasa abstrakcyjna C++ bez czystych funkcji wirtualnych?

class ShapeF 
{ 
public: 
    ShapeF(); 
    virtual ~ShapeF(); 

    inline void SetPosition(const Vector2& inPosition) { mPosition.Set(inPosition); } 

protected: 
    Vector2 mPosition; 
} 

Oczywiście z pewnym ommitied kodu, ale masz rację. Używam tego jako szablon, a także z niektórych Fun(), pominięte teksty stałe, sposób określić, jakiego rodzaju kształt używam

class RotatedRectangleF : public ShapeF 
{ 
public: 
    RotatedRectangleF(); 
    virtual ~RotatedRectangleF(); 
protected: 
    float mWidth; 
    float mHeight; 
    float mRotation; 
} 

ShapeF wykonuje swoją pracę z pozycjonowaniem i enum, który określa co typ to. Ma akcesory i mutatory, ale nie ma metod.

Czy mogę uczynić ShapeF klasą abstrakcyjną, aby upewnić się, że nikt nie próbuje i nie tworzy obiektu typu ShapeF?

Zwykle jest to wykonalne poprzez czystą funkcję wirtualną ciągu ShapeF

//ShapeF.h 
virtual void Collides(const ShapeF& inShape) = 0; 

Jednak jestem obecnie do czynienia z kolizji w klasie oddzielne. Mogę przenieść wszystko, ale zastanawiam się, czy istnieje sposób na streszczenie klasy ... bez czystych wirtualnych funkcji.

+0

Próbujesz reimplement dynamiczny wysyłkę z tagging (enum) i odlewanie ... że staną się wkrótce ból w przyszłości. Zastanowiłbym się nad projektem. –

+0

@ DavidRodríguez-dribeas Pomyślałem, że to najłatwiejsze podejście, static_casting wszystko. Gdybym chciał przeprojektować, całkowicie usunąłbym ShapeF(), z całym tym polimorfizmem, i by każdy kształt był jego własną osobą. Chyba, że ​​masz inną sugestię? – MintyAnt

Odpowiedz

39

Można zadeklarować, i wdrożenie, czystego wirtualnego destruktora:

class ShapeF 
{ 
public: 
    virtual ~ShapeF() = 0; 
    ... 
}; 

ShapeF::~ShapeF() {} 

Jest to mały krok od tego, co już masz, i zapobiegnie ShapeF od wystąpienia ich bezpośrednio. Klasy pochodne nie będą musiały się zmieniać.

+3

Szybkie pytanie - dlaczego '~ ShapeF' musi być zaimplementowany, gdy jest zadeklarowany jako" czysty wirtualny "? –

+0

Dzięki, to działa idealnie. Jakiś pomysł, dlaczego to działa? Czysty wirtualny nie może być zdefiniowany, pomyślałem. – MintyAnt

+4

To musi być zdefiniowane, lub klasy pochodne nie mogą zniszczyć swojej klasy bazowej. Można zdefiniować dowolną czystą funkcję wirtualną, która umożliwia delegowanym klasom delegowanie do nich. –

18

Spróbuj użyć chroniony konstruktor

+0

+1, destruktor powinien być "chroniony" i nie-wirtualny. Istnieje przypadek, w którym to nie rozwiąże problemu, jeśli 'ShapeF' jest' nowy'-ed i nigdy 'delete' -d (ale jest to błąd sam w sobie) –

+0

@ DavidRodríguez-dribeas Dlaczego powinien być chroniony destruktor? ? Jeśli jest chroniony, nie można usunąć obiektu. –

+0

@JamesKanze: Myślę, że * powinno * to trochę mocne słowo. Mam wrażenie, że jedynym powodem, dla którego destruktor jest "wirtualny", jest przestrzeganie zalecenia * zawsze * uczynienie destruktora wirtualnym, jeśli typ ma zostać wyprowadzony.Wykonanie 'protected 'destructor rozwiązuje ten sam podstawowy problem i zapewnia rozwiązanie problemu braku instancji (przynajmniej w stosie, i w stosie, chyba że jesteś zadowolony z wycieków pamięci :) W każdym razie mam wrażenie, że cały projekt powinien zostać powtórzony (jak wspomniałem w komentarzu do pytania). –

Powiązane problemy