2016-12-21 4 views
1

У меня есть класс под названием Widget. Этот класс является абстрактным и имеет виртуальные методы. Чтобы избежать обрезки объектов, все Widgets хранятся в виде ссылок или указателей. У меня есть несколько классов с конструкторами, которые хранят внутренне виджет, предоставленный им; таким образом, хранящийся файл Widget должен быть инициализирован вне конструктора и не может быть уничтожен до объекта, поэтому обычно Widget выделяется через динамическую память. Мой вопрос касается того, как обращаться с этой динамической памятью; Я составил список опций (не стесняйтесь предлагать другие). Какой из них самый идиоматический?Программный дизайн, связанный с полиморфизмом и управлением ресурсами

1. Умные указатели. Умные указатели кажутся правильным выбором, но поскольку я использую C++ 98, я должен написать свой собственный. Я также считаю, что письмо smart_pointer<Widget> все время немного уродливое.

2. Копия Widgets при хранении. Другим направлением является копия переданного Widget вместо оригинала. Это может вызвать обрезку объектов, но я не уверен. Кроме того, пользователи могут сами писать классы, которые хранят переданные в Widgets, и я бы не хотел, чтобы это было слишком сложно.

3. Позвольте пользователю обрабатывать все. Я мог бы заставить пользователя убедиться, что Widget удален вовремя. Кажется, это то, что Qt делает (?). Однако это снова усложняет ситуацию для пользователя.

+0

Я использовал бы умные указатели. Существует 'std :: auto_ptr', хотя он ошибочен. Если 'std :: auto_ptr' не выполняет задание, напишите одно или найдите уже написанное. – Galik

+1

И вы можете делать такие вещи, как 'typedef unique_pointer WidgetUPtr;' чтобы сделать ввод менее подробным. – Galik

+0

Кроме того, другим вариантом будет идиома 'clone'. https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor. Вы можете использовать его со своей * опцией 2 *, чтобы избежать нарезки объектов. –

ответ

1

лично мне нравится такой подход (это не всегда применимо, но я использовал его успешно несколько раз):

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 имеет виртуальный деструктор. Для полиморфного класса это не должно быть проблемой.

Обратите внимание, что после регистрации виджета его нельзя уничтожить, если все не уничтожено.

Преимущество этого подхода в том, что вы можете свободно перемещаться по указателям. Все они будут действительны до тех пор, пока хранилище не будет уничтожено. Это своего рода пул ручной работы.

+0

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

+0

Прежде всего, это не полный дизайн. Это скорее эскиз или шаблон. Он может/должен быть скорректирован с особой потребностью. Во-вторых, этот класс называется 'WidgetOwner'. Более чем понятно, что собственность передается классу. Этот шаблон ожидает только одного владельца. Как и все другие шаблоны проектирования, он не охватывает абсолютно все варианты использования. –

+0

Интересная идея ... если я предполагаю, что все виджеты динамически распределены (разумно), я могу заставить их зарегистрироваться. Кроме того, если по какой-то причине я решил, что Widget может быть освобожден до завершения программы, я могу добавить метод ForgetWidget() в WidgetOwner, который вызывается в деструкторе виджета, чтобы он не удалялся дважды. – Anonymous1847

0

Я думаю, что умный указатель - лучший выбор. И если вы чувствуете, что шаблон уродливый, попробуйте typedef

1

Какой из них наиболее идиоматический?

Наиболее идиоматические, несомненно, будет то, что последующие версии C++ решили быть «путь», и это было бы умными указатели (Вы можете найти/использовать реализацию на импульсе, например, также другие в Интернете может быть проще для вдохновения).

Вы также можете решить, что, поскольку вы используете c++98 (это огромный фактор, который следует принять во внимание), вы принимаете то, что идиоматично для этого контекста, и поскольку это было почти не на земле человека, ответ, скорее всего, сделанный дизайн является наиболее привлекательным для вас.

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

  • Нет связанных вопросов^_^