ami*_*mit 63 c++ smart-pointers covariance
我有这样的代码:
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 {...}
...
};
Run Code Online (Sandbox Code Playgroud)
此代码无法编译.
在视觉工作室,它提出
C2555:覆盖虚函数返回类型不同且不协变
如果我不使用boost::shared_ptr但返回原始指针,代码编译(我理解这是由于C++中的协变返回类型).我可以看到这个问题是因为boost::shared_ptr的Ret1不是源自boost::shared_ptr的RetInterface.但我想返回boost::shared_ptr的Ret1在其他类使用,否则我必须在返回后投返回值.
Ant*_*ams 24
首先,这确实是它在C++中的工作原理:派生类中虚函数的返回类型必须与基类中的相同.有一个特殊的例外,一个返回一个类X的引用/指针的函数可以被一个函数覆盖,该函数返回一个从X派生的类的引用/指针,但是你注意到它不允许智能指针(例如shared_ptr),仅用于普通指针.
如果您的界面RetInterface足够全面,那么您将不需要知道调用代码中的实际返回类型.一般来说它无论如何都没有意义:原因get_r是virtual函数首先是因为你将通过指针或对基类的引用来调用它AInterface,在这种情况下你不知道派生类会是什么类型返回.如果您使用实际A1引用来调用它,您可以创建一个单独的get_r1函数,以A1满足您的需要.
class A1: public AInterface
{
public:
boost::shared_ptr<RetInterface> get_r() const
{
return get_r1();
}
boost::shared_ptr<Ret1> get_r1() const {...}
...
};
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用访问者模式或类似我的Dynamic Double Dispatch技术将回调函数传递给返回的对象,然后可以使用正确的类型调用回调.
这篇博客文章中发布了一个巧妙的解决方案(来自 Raoul Borges)
在添加对多重继承和抽象方法的支持之前,摘录如下:
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 = c->clone();
cloneable * p = c.get();
std::unique_ptr<clonable> pp = p->clone();
}
Run Code Online (Sandbox Code Playgroud)
我鼓励阅读全文。它写得很简单并且解释得很好。
| 归档时间: |
|
| 查看次数: |
13615 次 |
| 最近记录: |