Копирование shared_ptr <Interface>для классов, которые действуют как значения - PullRequest
0 голосов
/ 06 мая 2018

Вот моя проблема. У меня есть интерфейс и два производных класса:

class Interface
{
public:
    virtual void f() = 0;
};
class Derived1 : public Interface;
class Derived2 : public Interface;

Затем у меня также есть класс Value, содержащий shared_ptr, целью которого является указание на один из двух производных классов:

class Value
{
public:
     Value();
     Value(const Value&);
private:
     shared_ptr<Interface> p_;
};

Поскольку я хочу, чтобы мой класс Value действовал как значение, я хочу, чтобы мой конструктор копирования создавал копию указанного производного объекта. Тем не менее, я не могу написать

Value::Value(const Value& value) : 
    p_(make_shared<Interface>(*value.p_))
{ }

как интерфейс содержит чисто виртуальную функцию. *value.p_ должен быть производным типом. Я не знаю, как правильно решить эту проблему.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Эта проблема как раз и предназначена для решения предлагаемой polymorphic_value (она передает семантику значений полиморфному объекту).

polymorphic_value<T> может владеть и выполнять глубокие копии объекта, полученного из T.

Предложение по ISO C ++ здесь http://wg21.link/p0201

Ссылочная реализация здесь https://github.com/jbcoe/polymorphic_value

Я являюсь автором как бумажной, так и справочной реализации.

Я обнаружил, что polymorphic_value полезен для удаления большого количества трудно записываемого шаблонного кода. Мне было бы интересно узнать, решит ли это и вашу проблему.

0 голосов
/ 07 мая 2018

Я не знаю, как правильно решить эту проблему.

Почему бы не использовать метод виртуального клона ()?

class Interface
{
public:
  virtual void f() = 0;
  virtual std::shared_ptr<Interface> clone()=0;
};

class Derived1 : public Interface {
    void f() {};
  std::shared_ptr<Interface> clone()
  {
    return std::make_shared<Derived1>(*this);
  }
};

Затем в конструкторе копирования вы можете использовать что-то вроде следующего для копирования указателя:

Value::Value(const Value& value)
{
    this->p_ = value.p_->clone();
}

Взгляните на это в качестве примера: http://www.cs.technion.ac.il/users/yechiel/c++-faq/copy-of-abc-via-clone.html

...