首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将协变返回类型与智能指针一起使用?

如何将协变返回类型与智能指针一起使用?
EN

Stack Overflow用户
提问于 2008-10-13 12:42:58
回答 7查看 17.2K关注 0票数 77

我的代码是这样的:

代码语言:javascript
运行
复制
class RetInterface {...}

class Ret1: public RetInterface {...}

class AInterface
{
  public:
     virtual boost::shared_ptr<RetInterface> get_r() const = 0;
     ...
};

class A1: public AInterface
{
  public:
     boost::shared_ptr<Ret1> get_r() const {...}
     ...
};

此代码无法编译。

在visual studio中,它引发

C2555:重写虚函数返回类型不同且不是协变的

如果我不使用boost::shared_ptr而是返回原始指针,代码就会编译(我知道这是由于C++中的covariant return types造成的)。我可以看到问题是因为Ret1boost::shared_ptr不是从RetInterfaceboost::shared_ptr派生的。但是我想返回Ret1boost::shared_ptr以便在其他类中使用,否则我必须在返回后强制转换返回值。

  1. 我做错了什么吗?
  2. 如果没有,为什么语言是这样的-它应该是可扩展的,以便在这种情况下处理智能指针之间的转换?是否有可取的解决方法?
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2008-10-13 09:58:40

首先,这确实是它在C++中的工作方式:派生类中虚函数的返回类型必须与基类中的相同。有一个特殊的例外,返回某个类X的引用/指针的函数可以被返回从X派生的类的引用/指针的函数覆盖,但正如您注意到的那样,这不允许智能指针(如shared_ptr),仅用于普通指针。

如果您的接口RetInterface足够全面,那么您就不需要知道调用代码中实际返回的类型。一般来说,这没有任何意义:get_r之所以是virtual函数,首先是因为您将通过指向基类AInterface的指针或引用来调用它,在这种情况下,您无法知道派生类将返回什么类型。如果你用一个实际的A1引用来调用它,你只需要在A1中创建一个独立的get_r1函数来做你需要的事情。

代码语言:javascript
运行
复制
class A1: public AInterface
{
  public:
     boost::shared_ptr<RetInterface> get_r() const
     {
         return get_r1();
     }
     boost::shared_ptr<Ret1> get_r1() const {...}
     ...
};

或者,您可以使用访问者模式或类似于我的Dynamic Double Dispatch技术来将回调传递给返回的对象,然后该对象可以使用正确的类型调用回调。

票数 31
EN

Stack Overflow用户

发布于 2019-06-11 19:24:38

this blog post上有一个整洁的解决方案(来自Raoul )

在添加对多重继承和抽象方法的支持之前,本文摘录如下:

代码语言:javascript
运行
复制
template <typename Derived, typename Base>
class clone_inherit<Derived, Base> : public Base
{
public:
   std::unique_ptr<Derived> clone() const
   {
      return std::unique_ptr<Derived>(static_cast<Derived *>(this->clone_impl()));
   }

private:
   virtual clone_inherit * clone_impl() const override
   {
      return new Derived(*this);
   }
};

class concrete: public clone_inherit<concrete, cloneable>
{
};

int main()
{
   std::unique_ptr<concrete> c = std::make_unique<concrete>();
   std::unique_ptr<concrete> cc = b->clone();

   cloneable * p = c.get();
   std::unique_ptr<clonable> pp = p->clone();
}

我鼓励阅读全文。它写得很简单,解释得也很好。

票数 4
EN

Stack Overflow用户

发布于 2008-10-13 04:49:45

在C++中重载方法时,不能更改返回类型(对于非指针、非引用的返回类型)。A1::get_r必须返回boost::shared_ptr<RetInterface>

安东尼·威廉姆斯有一个很好的全面的answer

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/196733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档