Вот проблема, у меня есть вектор указателей на абстрактный базовый класс, заполненный производными объектами, вот так:
class AbstractBase { /* ... */ };
clase Derived1 : public AbstractBase {
Derived1() { }
Derived1( const AbstractBase& abc ) { /* ... */ }
};
/* ... */
vector< AbstratcBase* > lThingies;
const AbstractBase& getThingie(int pos) {
return *lThingies[pos];
}
И чтобы получить копии элементов, я использую производный класс «конструктор копирования» следующим образом:
Derived1 d1 = getThingie(2);
Но проблема в том, что мне это не нравится: нет способа принудительно реализовать этот «конструктор копирования» при создании класса «output42», и даже если вы помните, очень легко ошибиться (например, сделать это). рекурсивный вызов, случилось со мной).
Мой вопрос: Есть лучший способ сделать это? как?
Обновить:
Одно из «неписаных» требований решения, которое я ищу, — это получить копию полученный объект как локальная переменная, поэтому я не забываю удалять Это.
Больше информации:
Есть ряд lThingies и во время выполнения я могу сказать, какие производные объекты содержатся в (производный1, производный2 и т. д.), но не во время компиляции.
Вы знаете свой getThingie
возвращает Derived1
? Если вы знаете это, возможно, вам следует изменить тип возвращаемого значения Derived1
и хранение в std::vector
быть Derived1
вместо AbstractBase
,
Предполагая, что выше не работает, вы можете сделать Derived1 bob = dynamic_cast<Derived1&>(getThingie(...));
, который во время выполнения проверяет, что вещь Derived1
или более производный экземпляр, и если это так, он выполняет приведение — если нет, он генерирует исключение.
Если вы не хотите беспокоиться о проверке времени выполнения, потому что вы настолько уверены, что это Derived1
, просто используйте Derived1 bob = static_cast<Derived1&>(getThingy(...));
,
Однако работа с реальными экземплярами классов, которые имеют иерархию наследования, очень сомнительна. Есть много, много вещей, которые могут пойти не так.
Вы могли бы сделать чисто виртуальный clone
функция в AbstractBase
который возвращает AbstractBase
указатель и переопределение clone
в ваших производных классах.
СТРОГО МНЕНИЕ:
Хотя это своего рода грубая и устаревшая практика (на мой взгляд). Я предлагаю ре-архитектуру, чтобы устранить необходимость делать это в первую очередь.
Для того, чтобы разработать на моем «грубое и устаревшее» мнение виртуального конструктора идиомы (я уверен, что это будет спорным):
class A
{
public:
virtual void toto() { std::cout << "Love Java" <<std::endl; }
virtual A&& Duplicate() { return std::move(A()); }
};
class B : public A
{
public:
virtual void toto() { std::cout << "Love C++11" <<std::endl; }
virtual B&& Duplicate() { return std::move(B()); }
};
int main()
{
A *a = new B();;
A&& b(a->Duplicate());
a->toto();
b.toto();
}
В основном вы создаете B в стеке, не зная его типа. (со ссылкой на rvalue в c ++ 11)