2009-09-18 11 views
8

Shape.hC++ alteradas temporalmente método no siendo llamada

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

Se utiliza la siguiente manera:

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 Forma :: Render y not Rect :: Render

Supongo que esto es porque está moldeando el Rect a Shape, pero no tengo idea de cómo detenerlo haciendo esto. Estoy tratando de dejar que cada forma controle cómo se renderiza anulando el método Render.

¿Alguna idea sobre cómo lograr esto?

+0

Tal vez usted quiere mostrarnos el código que crea los elementos del vector? –

+1

El problema y la solución son casi idénticos a esta pregunta http://stackoverflow.com/questions/1230006/. Como allí, tiene un vector de (struct containting a) clase base concreta, que debe crear mediante * slicing * clases derivadas si espera que se invoque Rect :: Render. –

Respuesta

19

Aquí es su problema:

struct ShapePointPair { 
     Shape shape; 
     Point location; 
}; 

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

Cuando se asigna un Rect a la Shape, está siendo copiado sólo la parte Shape (esto es objeto de cortar).

+0

auto_ptr perderá datos cuando ShapePointPair se copie en el vector – Mark

+0

@Mark: señaló, ta. – dave4420

+1

Gracias. Esperaba hacerlo sin punteros ya que las formas no usan mucha memoria, así que es fácil copiarlas en la pila, pero parece que eso no es posible. Gracias a todos por las respuestas rápidas. –

1

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

3

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

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

Gracias. No había escuchado sobre cortar antes, lo tendré en cuenta la próxima vez. –

2

El problema es que en su vector está almacenando copias de los objetos de forma, y ​​la copia de un objeto Shape no copia los datos o la funcionalidad de sus clases derivadas - Eres slicing el polimorfismo de distancia.

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

1

Está accediendo al objeto de forma directamente para la anulación del trabajo que necesita para acceder al objeto mediante un puntero o referencias.

Por ejemplo cuando cedida la Forma en el ShapePointPair El código 'rebanada' del objeto y sólo copiar el bit de la forma en la ShapePointPair

Hacer esto significa que usted tiene que ver la gestión de memoria - lo que podría utilizar un puntero inteligente en la estructura ShapePointPair { forma de smart_pointer; Ubicación del punto; };

0

No, no está emitiendo.

en su lugar puede almacenar una referencia a BaseClass Point:

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

Esta referencia debe fijarse en el tiempo de construcción de estructura ShapePointPair.Agregue un constructor a ShapePointPair para este propósito . Se deben pasar las instancias (recién creadas) de Rect.

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

Cuestiones relacionadas