У меня есть класс под названием Widget
, Этот класс является абстрактным и имеет виртуальные методы. Чтобы избежать нарезки всего объекта Widgets
хранятся в виде ссылок или указателей. У меня есть несколько классов с конструкторами, которые хранят внутренний виджет, данный им; Таким образом Widget
сохраненный должен быть инициализирован за пределами конструктора и не может быть уничтожен до объекта, поэтому обычно Widget
выделяется через динамическую память. Мой вопрос касается того, как обращаться с этой динамической памятью; Я составил список вариантов (не стесняйтесь предлагать другие). Какой из них наиболее идиоматичен?
1. Умные указатели. Умные указатели кажутся правильным выбором, но, поскольку я использую C ++ 98, я должен написать свой собственный. Я также думаю, что написание smart_pointer<Widget>
все время немного некрасиво.
2. Копировать Widgets
когда хранится. Другой способ действий — сохранить копию переданного Widget
вместо оригинала. Это может вызвать нарезку объектов, но я не уверен. Кроме того, пользователи могут захотеть написать классы, которые хранят переданные Widgets
и я не хотел бы сделать это слишком сложным.
3. Позвольте пользователю обрабатывать все. Я мог бы заставить пользователя убедиться, что Widget
удаляется вовремя. Похоже, это то, что делает Qt (?). Однако, это снова усложняет ситуацию для пользователя.
Мне лично нравится такой подход (он не всегда применим, но я успешно использовал его несколько раз):
class WidgetOwner
{
vector<Widget*> m_data;
public:
RegisterWidget(Widget *p) { m_data.push_back(p); }
~WidgetOwner() { for (auto &p : m_data) delete p; }
};
Этот простой класс просто хранит указатели. Этот класс может хранить любые производные Widget
при условии, что Widget
имеет виртуальный деструктор. Для полиморфного класса это не должно быть проблемой.
Обратите внимание, что как только Widget зарегистрирован, он не может быть уничтожен, пока все не будет уничтожено.
Преимущество этого подхода в том, что вы можете свободно обмениваться указателями. Все они будут действительны, пока хранилище не будет уничтожено. Это своего рода бассейн ручной работы.
Какой самый идиоматичный?
Конечно, самым идиоматичным было бы то, что в следующих версиях c ++ было решено стать «путем», и это было бы умные указатели (Например, вы можете найти / использовать реализацию для наддува, другие могут быть проще для вдохновения).
Вы также можете решить, что, поскольку вы используете c++98
(это огромный фактор, который нужно принимать во внимание), вы берете то, что идиоматично для этого контекста, и, поскольку это было практически ничем не предназначено для человека, ответ, скорее всего, заключается в том, какой домашний дизайн вам наиболее нравится.
Я думаю, что умный указатель — лучший выбор. И если вы чувствуете, что шаблон некрасив, попробуйте typedef