有没有一种方法可以复制派生 class 指针的向量而不将其强制转换为基础 class?

Is there a way to copy a vector of derived class pointers without casting it to the base class?

我有 4 个 class:1 个 Base、2 个 Derived 和 1 个 Container class。 Container class 包含 Base 个指针的向量。

我想为我的 class Container 创建一个复制构造函数,它不会将 Derived 指针转换为 Base,这样我就可以将Base 指向 Derived 之后的指针。

class Base {
   int m_base_attribute;
public:
   Base() : m_base_attribute(420) {}

   virtual void say_hello() {
      std::cout << "Hello !" << std::endl;
   }
};

class Derived : public Base {
   int m_derived_attribute;
public:
   Derived() : Base(), m_derived_attribute(69) {}

   virtual void say_hello() {
      std::cout << "I'm a derived class !" << std::endl;
   }
};

class Container {
   std::vector<Base*> m_base_vector;
public:
   Container() {
      m_base_vector.push_back(new Derived());
   }

   Container(const Container& model) {
      for(auto base : model.m_base_vector){
         m_base_vector.push_back(new Base(*base));
      }
   }

   ~Container() {
      for(auto base : m_base_vector) {
         delete base;
      }
   }
};

有没有办法做到没有任何内存泄漏?

问题是 new Base(*base) 总是创建一个 Base 对象,而不是 Derived 对象。这叫做slicing。解决方法是使用虚拟 clone 函数和虚拟析构函数:

class Base {
    int m_base_attribute;
public:
    // ...
    virtual std::unique_ptr<Base> clone() const
    {
        return std::make_unique<Base>(*this);
    }
    virtual ~Base() {}
};

class Derived : public Base {
    int m_derived_attribute;
public:
    // ...
    std::unique_ptr<Base> clone() const override
    {
        return std::make_unique<Derived>(*this);
    }
};

请注意,我使用 std::unique_ptr 而不是原始指针来避免内存泄漏。现在你可以在没有切片的情况下实现 Container class:

class Container {
    std::vector<std::unique_ptr<Base>> m_base_vector;
public:
    // ...    
    Container(const Container& model)
    {
        m_base_vector.reserve(model.m_base_vector.size());
        for (const auto& p : m_base_vector) {
            m_base_vector.push_back(p->clone());
        }
    }
};