在C++中clone()的最佳签名是什么?

Joh*_*McG 23 c++ clone smart-pointers covariant-return-types

正如Scott Myers写的那样,你可以利用C++的类型系统中的松弛来声明clone()返回一个指向所声明的实际类型的指针:

class Base
{
    virtual Base* clone() const = 0;
};

class Derived : public Base
{
    virtual Derived* clone() const
};
Run Code Online (Sandbox Code Playgroud)

编译器检测到clone()返回指向对象类型的指针,并允许Derived覆盖它以返回指向派生的指针.

希望让clone()返回一个智能指针,它意味着所有权语义的转移,如下所示:

class Base
{
   virtual std::auto_ptr<Base> clone() const = 0;
};

class Derived : public Base
{
    virtual std::auto_ptr<Derived> clone() const;
};
Run Code Online (Sandbox Code Playgroud)

不幸的是,约定的放宽并不适用于模板化的智能指针,编译器也不允许覆盖.

所以,似乎我有两个选择:

  1. 让clone()返回一个"哑"指针,并记录客户端负责处理它.
  2. 让clone()返回一个智能基指针,并让客户端使用dynamic_cast将它们保存到Derived指针(如果需要).

这些方法之一是首选吗?或者有没有办法让我吃掉我的所有权语义转移并且我的强大类型安全呢?

MSa*_*ers 26

使用公共非虚拟/私有虚拟模式:

class Base {
    public:
    std::auto_ptr<Base> clone () { return doClone(); }
    private:
    virtual Base* doClone() { return new (*this); }
};
class Derived : public Base {
    public:
    std::auto_ptr<Derived> clone () { return doClone(); }
    private:
    virtual Derived* doClone() { return new (*this); }
};
Run Code Online (Sandbox Code Playgroud)


Mat*_*ank 19

语法不是很好,但是如果你将它添加到上面的代码中,它不能解决你所有的问题吗?

template <typename T>
std::auto_ptr<T> clone(T const* t)
{
    return t->clone();
}
Run Code Online (Sandbox Code Playgroud)

  • 像这样.为了使它看起来像标准中的东西,建议将名称更改为make_clone()(类似于make_pair <>). (4认同)

Gor*_*pik 7

我认为在这种情况下函数语义是如此清晰,以至于几乎没有混淆的空间.因此,我认为您可以使用协变版本(返回指向真实类型的哑指针),并且您的调用者将知道他们正在获取其属性转移给他们的新对象.


cop*_*pro 5

这取决于您的使用案例.如果你认为你需要调用clone你知道它的动态类型的派生对象(记住,重点clone是允许在知道动态类型的情况下进行复制),那么你应该返回一个哑指针并将其加载到一个智能调用代码中的指针.如果没有,那么你只需要返回一个smart_ptr,这样你就可以随意返回所有覆盖.