14 December 2022

C++ 核心指南目录

“For making deep copies of polymorphic classes prefer a virtual clone function instead of public copy construction/assignment”

理由

不建议进行多态类的拷贝,因为会导致切片问题(slicing problem),参考 C.67。如果你确实需要拷贝语义,请进行深拷贝:提供一个虚的clone函数,实际拷贝继承类型,并返回一个指向新对象的所有权指针(owing pointer),并且在继承类返回共变式(covariant)继承类型。

例子

class B {
public:
    B() = default;
    virtual ~B() = default;
    virtual gsl::owner<B*> clone() const = 0;
protected:
     B(const B&) = default;
     B& operator=(const B&) = default;
     B(B&&) = default;
     B& operator=(B&&) = default;
    // ...
};

class D : public B {
public:
    gsl::owner<D*> clone() const override
    {
        return new D{*this};
    };
};

一般来说,建议使用智能指针表示所有权(参考 R.20)。但是,根据语言规则,共变式(covariant)返回类型不能是智能指针: 当 B::clone 返回 unique_ptr<B> 的时候 D::clone 不能返回 unique_ptr<D> 。因此,要么你在所有的重载函数中,始终如一地返回 unique_ptr<B> ,要么使用 Guidelines Support Library 中的 owner<> 工具。