使用智能指针返回类型协方差

Arm*_*yan 32 c++ virtual-functions smart-pointers return-type

在C++中我们可以这样做:

struct Base
{
   virtual Base* Clone() const { ... }
   virtual ~Base(){}
};

struct Derived : Base
{
   virtual Derived* Clone() const {...} //overrides Base::Clone
};
Run Code Online (Sandbox Code Playgroud)

但是,以下内容不会做同样的伎俩:

struct Base
{
   virtual shared_ptr<Base> Clone() const { ... }
   virtual ~Base(){}
};

struct Derived : Base
{
   virtual shared_ptr<Derived> Clone() const {...} //hides Base::Clone
};
Run Code Online (Sandbox Code Playgroud)

在此示例中Derived::Clone 隐藏 Base::Clone而不是覆盖它,因为标准表示重写成员的返回类型可能仅从引用(或指针)更改为基础到引用(或指针).这有什么聪明的解决方法吗?当然有人可能认为Clone函数应该返回一个普通的指针,但是现在让我们忘记它 - 这只是一个例证.我正在寻找一种方法来启用虚拟功能的返回类型从智能指针更改Base为智能指针Derived.

提前致谢!

更新:感谢 Iammilind,我的第二个例子确实无法编译

yme*_*ett 47

您无法直接执行此操作,但在非虚拟接口惯用法的帮助下,有几种方法可以模拟它.

在原始指针上使用协方差,然后将它们包装起来

struct Base
{
private:
   virtual Base* doClone() const { ... }

public:
   shared_ptr<Base> Clone() const { return shared_ptr<Base>(doClone()); }

   virtual ~Base(){}
};

struct Derived : Base
{
private:
   virtual Derived* doClone() const { ... }

public:
   shared_ptr<Derived> Clone() const { return shared_ptr<Derived>(doClone()); }
};
Run Code Online (Sandbox Code Playgroud)

这只适用于你实际上有一个原始指针开始.

通过铸造模拟协方差

struct Base
{
private:
   virtual shared_ptr<Base> doClone() const { ... }

public:
   shared_ptr<Base> Clone() const { return doClone(); }

   virtual ~Base(){}
};

struct Derived : Base
{
private:
   virtual shared_ptr<Base> doClone() const { ... }

public:
   shared_ptr<Derived> Clone() const
      { return static_pointer_cast<Derived>(doClone()); }
};
Run Code Online (Sandbox Code Playgroud)

在这里,你必须确保Derived::doClonedo的所有覆盖实际上返回指针Derived或从它派生的类.

  • 这仍然是C++需要解决的最重要的事情之一.在任何地方使用shared_ptr都非常有用,但这样做仍然是一个很大的麻烦. (3认同)
  • +1这是我推荐的解决方案.(嗯,实际上,我已经开始建议不使用`shared_ptr`.函数返回`shared_ptr`的政策很少.但同样的解决方案适用于`auto_ptr`或其他智能指针.) (2认同)