14 December 2022

C++ 核心指南目录

C.130: 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<>工具。