Переопределенный метод C ++ не вызывается
-
22-07-2019 - |
Вопрос
Форма.h
namespace Graphics {
class Shape {
public:
virtual void Render(Point point) {};
};
}
Прямая кишка.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::Render
и не Rect::Render
Я предполагаю, что это происходит потому, что он разыгрывает Rect
к a Shape
, но я понятия не имею, как остановить это.Я пытаюсь позволить каждой фигуре управлять тем, как она визуализируется, переопределяя Render
способ.
Есть какие-нибудь идеи о том, как этого добиться?
Решение
Вот ваша проблема:
struct ShapePointPair {
Shape shape;
Point location;
};
Вы храните Shape
.Вы должны хранить Shape *
, или shared_ptr<Shape>
или что-то.Но не Shape
;C++ — это не Java.
Когда вы назначаете Rect
к Shape
, только Shape
часть копируется (это нарезка объекта).
Другие советы
Эта проблема называется нарезкой — при копировании в базу вы теряете производный функционал.Чтобы избежать этого, используйте указатели на базовый класс, т.е.
std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);
Проблема в том, что в вашем векторе вы храните копии объектов Shape, а копирование объекта Shape не копирует данные или функциональность его производных классов — вы нарезка полиморфизм прочь.
Управляйте объектами с помощью функций «Создать» и «Удалить», а также организуйте в векторе сохранение указателей на них.
Полиморфизм будет работать только с указателем на фигуру, а не с объектом фигуры.
Вы получаете доступ к объекту формы напрямую, чтобы переопределение работало. Вам необходимо получить доступ к объекту через указатель или ссылки.
Например, когда вы назначаете форму в ShapePointPair, код «разрезает» объект и копирует только бит формы в ShapePointPair.
Это будет означать, что вы должны наблюдать за управлением памятью - чтобы вы могли использовать умный указатель в форме struct shapepointpair {smart_pointer;Расположение точки;};
Нет, это не кастинг.
Вместо этого вы можете сохранить ссылку на базовый класс Point:
struct ShapePointPair {
Shape shape;
Point &location;
};
Эта ссылка должна быть установлена во время построения для struct ShapePointPair.Добавьте конструктор в ShapePointPair для этой цели.Должны быть переданы (вновь созданные) экземпляры Rect.
Также обратите внимание на ответственность за управление памятью (правильные написанные деструкторы и т.д.).
Вы можете попробовать boost::ptr_vector
http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html
Я не уверен, что смогу хорошо объяснить, потому что у меня плохой английский.
Я думаю, вам придется использовать его ссылочный тип или тип указателя.потому что форма точно определяет, что она должна делать.
Если вы используете свой код напрямую, ваш ребенок попытается скопировать и выполнить работу с фигурами.Вот почему не работает ваша функция переопределения.
Используйте указатель или ссылку, как это.
указатель.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;
}
ссылка.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;
}
*пс:лично я использую абстрактную функцию (virtual void Something() = 0;).потому что я тоже иногда забывал об этом, поэтому воспринимаю это как синтаксическую ошибку.