Pregunta

Forma.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;
};

Usado así:

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

for(int i = 0; i < theShapes.size(); i++) {
    theShapes[i].shape.Render(theShapes[i].location);
}

Este código termina llamando Shape::Render y no Rect::Render

Supongo que esto se debe a que está emitiendo el Rect a un Shape, pero no tengo idea de cómo evitar que haga esto.Estoy tratando de dejar que cada forma controle cómo se representa anulando el Render método.

¿Alguna idea sobre cómo lograr esto?

¿Fue útil?

Solución

Aquí está tu problema:

struct ShapePointPair {
        Shape shape;
        Point location;
};

Estás almacenando un Shape. Debería almacenar un Shape *, o un shared_ptr<Shape> o algo así. Pero no un Rect; C ++ no es Java.

Cuando asigna un <=> a <=>, solo se copia la parte <=> (esto es segmentación de objetos ).

Otros consejos

Este problema se llama segmentación: pierde la funcionalidad derivada al copiar en una base. Para evitar esto, use punteros a la clase base, es decir,

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

El problema es que en su vector está almacenando copias de objetos Shape, y copiar un objeto Shape no copia los datos o la funcionalidad de sus clases derivadas: usted es segmentando el polimorfismo de distancia.

Administre los objetos usando new y delete, y organice su vector para almacenar punteros a ellos.

El polimorfismo solo funcionará desde un puntero a una forma, no desde un objeto de forma.

Está accediendo al objeto de forma directamente para que funcione la anulación. Necesita acceder al objeto a través de un puntero o referencias.

Por ejemplo, cuando asigna la Forma al ShapePointPair, el código 'cortará' el objeto y solo copiará el bit de la Forma en el ShapePointPair

Hacer esto significará que debe observar la administración de memoria, por lo que podría usar un puntero inteligente en la estructura     ShapePointPair {            forma de puntero inteligente;             Ubicación del punto;     };

No, no se está emitiendo.

En su lugar, puede almacenar una referencia al punto de clase base:

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

Esta referencia debe establecerse en tiempo de construcción para struct ShapePointPair. Agregue un constructor a ShapePointPair para esto propósito. Se deben pasar instancias (recién creadas) de Rect.

Observe también las responsabilidades de administración de memoria (adecuada destructores escritos, etc.).

No estoy seguro de explicar bien porque mi inglés es pobre.

Creo que debería tener que usarlo como referencia o tipo de puntero. porque la forma se define exactamente lo que tiene que hacer.

Si usa su código directamente, su hijo intenta copiar y hacer que la forma funcione. Es por eso que no funciona su función de anulación.

usa puntero o referencia como este.

puntero.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;
}

referencia.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 función abstracta (virtual void something () = 0;).  porque a veces también lo olvidé, así que lo cojo como error de sintaxis.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top