Metodo C ++ ignorato che non viene chiamato
-
22-07-2019 - |
Domanda
Shape.h
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;
};
Usato 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
Suppongo che ciò avvenga perché sta trasmettendo Rect
in Shape
, ma non ho idea di come fermarlo. Sto cercando di lasciare che ogni forma controlli il modo in cui viene renderizzata sostituendo il metodo Render
.
Qualche idea su come raggiungere questo obiettivo?
Soluzione
Ecco il tuo problema:
struct ShapePointPair {
Shape shape;
Point location;
};
Stai memorizzando un Shape
. Dovresti archiviare un Shape *
o un shared_ptr<Shape>
o qualcosa del genere. Ma non un Rect
; C ++ non è Java.
Quando si assegna un <=> a <=>, viene copiata solo la parte <=> (si tratta di suddivisione in oggetti ).
Altri suggerimenti
Questo problema si chiama slicing: si perde la funzionalità derivata quando si copia su una base. Per evitare ciò, utilizzare i puntatori alla classe base, ad esempio
std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);
Il problema è che nel tuo vettore stai memorizzando copie degli oggetti Shape e la copia di un oggetto Shape non copia i dati o la funzionalità delle sue classi derivate - sei tagliando il polimorfismo via.
Gestisci gli oggetti usando new ed elimina e organizza che il tuo vettore memorizzi i puntatori su di essi.
Il polimorfismo funzionerà solo da un puntatore a una forma, non da un oggetto forma.
Stai accedendo direttamente all'oggetto forma affinché la sostituzione funzioni per accedere all'oggetto tramite un puntatore o riferimenti.
Ad esempio, quando si assegna Shape in ShapePointPair, il codice "suddivide" l'oggetto e copia solo il bit Shape in ShapePointPair
Ciò significa che devi guardare la gestione della memoria, in modo da poter usare un puntatore intelligente nella struttura ShapePointPair { forma smart_pointer; Posizione del punto; };
No, non è casting.
È possibile invece memorizzare un riferimento a Punto base:
struct ShapePointPair {
Shape shape;
Point &location;
};
Questo riferimento deve essere impostato in fase di costruzione per struct ShapePointPair. Aggiungi un costruttore a ShapePointPair per questo scopo. Deve essere passata istanze (appena create) di Rect.
Osservare anche le responsabilità di gestione della memoria (corretta distruttori scritti, ecc.).
Potresti provare boost :: ptr_vector
http://www.boost.org /doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html
Non sono sicuro di spiegare bene perché il mio inglese è scadente.
Penso che dovresti usarlo come riferimento o tipo di puntatore. perché la forma è esattamente definita cosa deve fare.
Se usi direttamente il tuo codice, tuo figlio prova a copiare e fa funzionare la forma. Ecco perché non funziona la tua funzione di override.
usa puntatore o riferimento come questo.
pointer.h
class Parent {
public:
virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
Parent* obj1;
Parent* obj2;
};
int main() {
Child1 child1;
Child2 child2;
Holder holder = { &child1, &child2 };
holder.obj1->work();
holder.obj2->work();
return 0;
}
reference.h
class Parent {
public:
virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
Parent& obj1;
Parent& obj2;
};
int main() {
Child1 child1;
Child2 child2;
Holder holder = { child1, child2 };
holder.obj1.work();
holder.obj2.work();
return 0;
}
* ps: personalmente uso la funzione astratta (vuoto virtuale qualcosa () = 0;). perché a volte me ne sono anche dimenticato, quindi lo prendo come errore di sintassi.