2013-01-31 16 views
13

Ho una classe di baseClasse astratta C++ senza pure funzioni virtuali?

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

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

protected: 
    Vector2 mPosition; 
} 

Ovviamente con un codice ommitied, ma si ottiene il punto. Io uso questo come un modello, e con un certo divertimento enumerazioni (ommited), un modo per determinare che tipo di forma che sto utilizzando

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

ShapeF fa il suo lavoro con il posizionamento, e un enum che definisce il tipo è Dispone di accessori e mutatori, ma non di metodi.

Posso rendere ShapeF una classe astratta, per garantire che nessuno provi e istanzia un oggetto di tipo ShapeF?

Normalmente, questo è fattibile avendo una funzione virtuale pura all'interno ShapeF

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

Tuttavia, sono attualmente a che fare con le collisioni in una classe separata. Posso spostare tutto, ma mi chiedo se c'è un modo per fare una classe astratta .. senza le pure funzioni virtuali.

+0

Si sta tentando di reimplementare spedizione dinamico con codifica (enum) e la fusione ... che diventerà un dolore ben presto in futuro. Vorrei riconsiderare il design. –

+0

@ DavidRodríguez-dribeas Ho pensato che questo fosse l'approccio più semplice, static_casting di tutto. Se volessi riprogettare, rimuoverei ShapeF() del tutto, con tutto il polimorfismo, e fare in modo che ogni forma fosse la propria persona. A meno che tu non abbia avuto un suggerimento diverso? – MintyAnt

risposta

39

Si poteva dichiarare, e implementare, un distruttore virtuale pura:

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

ShapeF::~ShapeF() {} 

E 'un piccolo passo da ciò che già avete, e impedirà ShapeF dall'essere un'istanza direttamente. Le classi derivate non avranno bisogno di cambiare.

+3

Domanda veloce: perché '~ ShapeF' deve essere implementato quando viene dichiarato' puro virtuale'? –

+0

Grazie, funziona perfettamente. Qualche idea del perché questo funziona? Un puro virtuale non può essere definito, pensavo. – MintyAnt

+4

Deve essere definito, o le classi derivate non possono distruggere la loro classe base. È possibile definire qualsiasi funzione virtuale pura, che consente alle classi derivate di delegare ad esse. –

18

Provare a usare un costruttore protetto

+0

+1, il distruttore dovrebbe essere "protetto" e non virtuale. C'è un caso d'angolo in cui questo non risolve il problema, se 'ShapeF' è' new'-ed e mai 'delete'-d (ma questo è un bug in sé) –

+0

@ DavidRodríguez-dribeas Perché il distruttore dovrebbe essere protetto ? Se è protetto, non è possibile eliminare l'oggetto. –

+0

@JamesKanze: Credo che * dovrebbe * è un po 'una parola forte. Ho la sensazione che l'unica ragione per cui il distruttore sia 'virtuale' è di seguire la raccomandazione di * sempre * che rende il distruttore virtuale se il tipo deve essere derivato.Rendere "protetto" il distruttore risolve lo stesso problema di fondo e fornisce una soluzione al problema della non istanziazione (almeno nello stack e nell'heap a meno che non si sia soddisfatti delle perdite di memoria :) In ogni caso la mia sensazione è che l'intero il design dovrebbe essere rivisitato (come ho detto nel commento alla domanda) –