Вот сюжет вопроса: предположим, у меня есть некоторые абстрактные классы для объектов, назовем его Object
. Это определение будет включать в себя 2D положение и размеры. Пусть у него также есть метод virtual void Render(Backend& backend) const = 0
, используемый для рендеринга.
Теперь я специализируюсь на своем дереве наследования и добавляю классы Rectangle
и Ellipse
. Думаю, у них не будет своих свойств, но у них будет свой virtual void Render
метод. Допустим, я реализовал эти методы, так что Render
для Rectangle
фактически рисует некоторый прямоугольник, и то же самое для эллипса.
Теперь я добавляю некоторый объект с именем Plane
, который определяется как class Plane : public Rectangle
и имеет закрытый член std::vector<Object*> plane_objects;
Сразу после этого я добавляю метод для добавления какого-либо объекта в мою плоскость.
И тут возникает вопрос. Если я спроектирую этот метод как void AddObject(Object& object)
, я столкнусь с проблемой, так как не смогу вызывать виртуальные функции, потому что я бы сделать что-то вроде plane_objects.push_back(new Object(object));
, и это должно быть push_back(new Rectangle(object))
для прямоугольников и new Circle(...)
для кругов.
Если я реализую этот метод как void AddObject(Object* object)
, он выглядит хорошо, но затем где-то еще это означает выполнение вызова, как plane.AddObject(new Rectangle(params));
, и это обычно беспорядок, потому что тогда неясно, какая часть моей программы должна освободить выделенную память ,
["при уничтожении самолета? Почему? Мы уверены, что вызовы AddObject
были сделаны только как AddObject(new something
).]
Я полагаю, что проблемы, вызванные использованием второго подхода, можно решить с помощью интеллектуальных указателей, но я уверен, что должно быть что-то лучшее.
Есть идеи?