2009-09-18 3 views
8

Shape.hC++ override metodo non sempre chiamato

namespace Graphics { 
class Shape { 
public: 
    virtual void Render(Point point) {}; 
}; 
} 

Rect.h

namespace Graphics { 

    class Rect : public Shape { 

    public: 

     Rect(float x, float y); 
     Rect(); 

     void setSize(float x, float y); 

     virtual void Render(Point point); 


    private: 

     float sizeX; 
     float sizeY; 

    }; 

} 

struct ShapePointPair { 
    Shape shape; 
    Point location; 
}; 

Utilizzato in questo modo:

std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList(); 

for(int i = 0; i < theShapes.size(); i++) { 

    theShapes[i].shape.Render(theShapes[i].location); 

} 

Questo codice finisce per chiamare Shape :: Render e non Rect :: Render

Presumo che questo sia perché sta lanciando Rect a Shape, ma non ho idea di come smettere di farlo. Sto provando a lasciare che ogni forma controlli come viene eseguita sovrascrivendo il metodo Render.

Qualche idea su come ottenere questo risultato?

+0

Forse si vuole mostrarci il codice che crea gli elementi vettoriali? –

+1

Il problema e la soluzione sono quasi identici a questa http://stackoverflow.com/questions/1230006/ question. Come là, hai un vettore di (struct containting a) una classe base concreta, che devi creare mediante * slicing * classi derivate se ti aspetti che Rect :: Render sia chiamato. –

risposta

19

Ecco il problema:

struct ShapePointPair { 
     Shape shape; 
     Point location; 
}; 

si archiviano un Shape. È necessario memorizzare un Shape * o un shared_ptr<Shape> o qualcosa del genere. Ma non un Shape; C++ non è Java.

quando si assegna un Rect al Shape, solo la parte Shape viene copiato (questo è oggetto affettare).

+0

auto_ptr perderà i dati man mano che ShapePointPair viene copiato nel vettore – Mark

+0

@Mark: annotato, ta. – dave4420

+1

Grazie. Speravo di farlo senza indicazioni perché le forme non usano molta memoria quindi sono semplici da copiare sullo stack, ma sembra che non sia possibile. Grazie a tutti per le risposte veloci. –

1

Il polimorfismo funziona solo da un puntatore a una forma, non da un oggetto forma.

3

Questo problema si chiama slicing: si perde la funzionalità derivata quando si copia su una base. Per evitare questo uso puntatori alla classe base, vale a dire

std::vector<Graphics::Shape*> s; 
s.push_back(&some_rect); 
+0

Grazie. Non avevo sentito parlare di affettare prima, lo terrò a mente la prossima volta. –

2

Il problema è che nel vostro vettore si archiviano copie di oggetti Shape, e copia di un oggetto Shape non copia i dati o le funzionalità dei suoi classi derivate - Sei slicing il polimorfismo di distanza.

Gestisci gli oggetti utilizzando nuovi e cancella e ordina che il tuo vettore memorizzi loro dei puntatori.

1

Si sta accedendo direttamente all'oggetto forma affinché la modifica funzioni per accedere all'oggetto tramite un puntatore o riferimenti.

Per esempio, quando si assigne la forma nella ShapePointPair il codice sara 'fetta' l'oggetto e solo copiare il bit Shape nella ShapePointPair

Fare questo significa che devi guardare la gestione della memoria - così si potrebbe usare un puntatore intelligente nella struct ShapePointPair { forma smart_pointer; Posizione del punto; };

0

No, non è un casting.

si può invece memorizzare un riferimento a BaseClass Point:

struct ShapePointPair { 
     Shape shape; 
     Point &location; 
}; 

Tale riferimento deve essere impostata in fase di costruzione per struct ShapePointPair.Aggiungi un costruttore a ShapePointPair per questo scopo . Deve essere passato (appena creato) istanze di Rect.

Osservare inoltre le responsabilità di gestione della memoria (appropriati distruttori scritti , ecc.).