Рассмотрим следующие классы
class Base {
public:
virtual void do_stuff() = 0;
};
class Derived : public Base {
public
virtual void do_stuff() { std::cout << "I'm useful"; };
};
Теперь скажем, что я хочу иметь еще один класс, ответственный за владение объектами Base производных типов и перебирать их, называя их метод do_stuff(). Это похоже на это, но я не знаю, что T следует объявить как
class Owner {
public:
void do_all_stuff() {
//iterate through all items and call do_stuff() on them
}
void add_item(T item) {
items.push_back(item);
}
vector<T> items;
}
Я вижу несколько возможностей:
T не может быть Base, так как я мог бы только добавлять объекты конкретного типа Base, так что не может быть и речи.
T может быть Base* или Base&, но теперь мне нужно доверять вызывающему устройству add_item(), чтобы передать мне указатель или ссылку на объект, который будет существовать, когда я его извлечу из items. Я не могу delete элементы в деструкторе Owner, так как я не знаю, что они были динамически распределены. Однако они должны быть delete 'd, если бы они были, что оставляет меня с двусмысленным владением.
T может быть Base* или Base&, и я добавляю метод Base* create_item<DerivedT>() { return new DerivedT; } к Owner. Таким образом, я знаю, что указатель останется в силе, и я его сохраню, но я не могу вызвать конструктор не по умолчанию на DerivedT. Кроме того, Owner становится ответственным за создание экземпляров объектов. Я также должен удалить каждый элемент в деструкторе Owner, хотя это и не проблема.
В принципе, я хотел бы сделать что-то похожее на:
Owner owner;
void add_one() {
Derived d;
owner.add_item(d);
}
void ready() {
owner.do_all_stuff();
}
void main() {
for(int i = 0; i < 10; ++i) {
add_one();
}
ready();
}
Я уверен, что там что-то связано с семантикой перемещения (я мог перемещать объекты, переданные в add_items(), чтобы их владеть), но я до сих пор не могу понять, как будет объявлена моя коллекция.
Что такое идиома С++ для такого рода полиморфного владения (в частности, с контейнерами STL)?