2009-09-18 8 views
8

Shape.hC++ Переопределенный метод не вызывался

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

Используется так:

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

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

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

} 

Этот код заканчивается вызовом Shape :: Рендер и не Rect :: Render

Я предполагаю, что это потому что он отличает Rect к форме, но я не знаю, как остановить это. Я пытаюсь разрешить каждой форме управлять тем, как она визуализируется путем переопределения метода Render.

Любые идеи о том, как достичь этого?

+0

Может быть, вы хотите, чтобы показать нам код, который создает векторные элементы? –

+1

Проблема и решение почти идентичны этому вопросу http://stackoverflow.com/questions/1230006/. Как там, у вас есть вектор (struct содержащий а) конкретный базовый класс, который вы должны создавать с помощью * slicing * производных классов, если вы ожидаете вызова Rect :: Render. –

ответ

19

Вот ваша проблема:

struct ShapePointPair { 
     Shape shape; 
     Point location; 
}; 

Вы хранения Shape. Вы должны хранить Shape * или shared_ptr<Shape> или что-то в этом роде. Но не Shape; C++ - это не Java.

Когда вы назначаете Rect к Shape, только Shape часть копируется (это объект нарезка).

+0

auto_ptr потеряет данные, поскольку ShapePointPair скопирован вокруг в векторе – Mark

+0

@Mark: отмечено, ta. – dave4420

+1

Спасибо. Я надеялся сделать это без указателей, так как формы не используют много памяти, поэтому их просто скопировать в стек, но, похоже, это невозможно. Спасибо всем за быстрые ответы. –

1

Полиморфизм будет работать только от указателя к форме, а не от объекта формы.

3

Эта проблема называется slicing - вы теряете производную функциональность при копировании на базу. Чтобы избежать этого, использование указателей на базовый класс, т.е.

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

Спасибо. Раньше я не слышал про нарезку, это будет иметь в виду в следующий раз. –

2

Проблема заключается в том, что в вашем векторе вы храните копии объектов Shape и копирование Shape объект не копирует данные или функциональные возможности его производных классов - вы от slicing полиморфизма.

Управление объектами с использованием новых и удаления и упорядочение для вашего вектора для хранения указателей на них.

1

Вы получаете доступ к объекту фигуры непосредственно для переопределения, чтобы работать, вам нужно получить доступ к объекту с помощью указателя или ссылок.

Например, когда вы assigne форма в ShapePointPair код будет «срез» объекта и копировать только немного Shape в ShapePointPair

Делать это будет означать, что вы должны следить за управление памятью - так что вы могли бы использовать умный указатель в структуре ShapePointPair { smart_pointer shape; Местоположение точки; };

0

Нет, это не литье.

Вы можете вместо этого сохранить ссылку на BaseClass Point:

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

Эта ссылка должна быть установлена ​​во время строительства для структуры ShapePointPair.Добавьте конструктор в ShapePointPair для этой цели . Должны быть переданы (вновь созданные) экземпляры Rect.

Также соблюдайте ответственность за управление памятью (надлежащие письменные деструкторы и т. Д.).

Смежные вопросы