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?

È stato utile?

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.).

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top