返回类型与智能指针的协方差 [英] Return Type Covariance with Smart Pointers

查看:141
本文介绍了返回类型与智能指针的协方差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

struct Derived:Base
{
virtual Derived * Clone()const {...} //覆盖Base :: Clone
};然而,以下不会做同样的伎俩:









< b $ b

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

struct Derived:Base
{
virtual shared_ptr< Derived> Clone()const {...} //隐藏Base :: Clone
};

在此示例中 Derived :: Clone 隐藏 Base :: Clone ,而不是覆盖重写成员的类型可以仅从引用(或指针)改变到引用(或指针)到引用。有什么聪明的解决方法吗?当然可以认为 Clone 函数应该返回一个简单的指针,但让我们现在忘记它 - 这只是一个说明性的例子。我正在寻找一种方法,使虚拟函数的返回类型从智能指针 Base 改为智能指针 Derived



提前感谢!

我的第二个例子确实不编译,感谢 Iammilind

解决方案

你不能直接做,但有几种方法来模拟它, - 虚拟接口习惯。



对原始指针使用协方差,然后将它们包装



  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()); }
};

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



通过转换来模拟协方差



  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()); }
};

这里必须确保所有覆盖 Derived :: doClone 实际上返回指向 Derived 或从其派生的类的指针。


In C++ we can do this:

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

struct Derived : Base
{
   virtual Derived* Clone() const {...} //overrides Base::Clone
};

However, the following won't do the same trick:

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

struct Derived : Base
{
   virtual shared_ptr<Derived> Clone() const {...} //hides Base::Clone
};

In this example Derived::Clone hides Base::Clone rather than overrides it, because the standard says that the return type of an overriding member may change only from reference(or pointer) to base to reference (or pointer) to derived. Is there any clever workaround for this? Of course one could argue that the Clone function should return a plain pointer anyway, but let's forget it for now - this is just an illustratory example. I am looking for a way to enable changing the return type of a virtual function from a smart pointer to Base to a smart pointer to Derived.

Thanks in advance!

Update: My second example indeed doesn't compile, thanks to Iammilind

解决方案

You can't do it directly, but there are a couple of ways to simulate it, with the help of the Non-Virtual Interface idiom.

Use covariance on raw pointers, and then wrap them

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()); }
};

This only works if you actually have a raw pointer to start off with.

Simulate covariance by casting

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()); }
};

Here you must make sure that all overrides of Derived::doClone do actually return pointers to Derived or a class derived from it.

这篇关于返回类型与智能指针的协方差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆