Подтвердить что ты не робот

Как скопировать/создать экземпляр производного класса из указателя в полиморфный базовый класс?

Я долгое время боролся с такой проблемой, поэтому я решил спросить здесь.

class Base {
  virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...

// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);

Метод должен возвращать динамически создаваемую копию или, по крайней мере, хранить объект в стеке в какой-либо структуре данных, чтобы избежать проблемы с возвратом временного файла.

Наивный подход к реализации вышеупомянутого метода будет заключаться в использовании нескольких typeid или dynamic_cast в серии if-операторов для проверки каждого возможного производного типа, а затем использования оператора new. Есть ли другой подход?

P.S.: Я знаю, что этой проблемы можно избежать с помощью интеллектуальных указателей, но меня интересует минималистический подход, без кучи библиотек.

4b9b3361

Ответ 1

Вы добавляете virtual Base* clone() const = 0; в свой базовый класс и соответствующим образом реализуете его в своих классах Derived. Если ваш Base не абстрактный, вы можете, конечно, вызвать его конструктор-копию, но это немного опасно: если вы забудете реализовать его в производном классе, вы получите (возможно, нежелательную) нарезку.

Если вы не хотите дублировать этот код, вы можете использовать идентификатор CRTP для реализации функции через шаблон:

template <class Derived>
class DerivationHelper : public Base
{
public:
  virtual Base* clone() const
  {
    return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
  }
};

class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };

Ответ 2

Альтернативой является наличие чистого виртуального метода CreateCopy() в общей базе, который реализуется в каждом производном классе.