我的代码是这样的:
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造成的)。我可以看到问题是因为Ret1
的boost::shared_ptr
不是从RetInterface
的boost::shared_ptr
派生的。但是我想返回Ret1
的boost::shared_ptr
以便在其他类中使用,否则我必须在返回后强制转换返回值。
发布于 2008-10-13 09:58:40
首先,这确实是它在C++中的工作方式:派生类中虚函数的返回类型必须与基类中的相同。有一个特殊的例外,返回某个类X的引用/指针的函数可以被返回从X派生的类的引用/指针的函数覆盖,但正如您注意到的那样,这不允许智能指针(如shared_ptr
),仅用于普通指针。
如果您的接口RetInterface
足够全面,那么您就不需要知道调用代码中实际返回的类型。一般来说,这没有任何意义:get_r
之所以是virtual
函数,首先是因为您将通过指向基类AInterface
的指针或引用来调用它,在这种情况下,您无法知道派生类将返回什么类型。如果你用一个实际的A1
引用来调用它,你只需要在A1
中创建一个独立的get_r1
函数来做你需要的事情。
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技术来将回调传递给返回的对象,然后该对象可以使用正确的类型调用回调。
发布于 2019-06-11 19:24:38
在this blog post上有一个整洁的解决方案(来自Raoul )
在添加对多重继承和抽象方法的支持之前,本文摘录如下:
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();
}
我鼓励阅读全文。它写得很简单,解释得也很好。
发布于 2008-10-13 04:49:45
在C++中重载方法时,不能更改返回类型(对于非指针、非引用的返回类型)。A1::get_r
必须返回boost::shared_ptr<RetInterface>
。
安东尼·威廉姆斯有一个很好的全面的answer。
https://stackoverflow.com/questions/196733
复制相似问题