我有一个通用的结构
template<typename X, typename Y>
struct S
{
};
然后有一个抽象类,它在纯虚函数中返回上面struct的共享指针。其中一个派生类也实现了这个函数,但是需要使用不同的实例化类型返回指向S的指针:
typedef boost::shared_pointer<S<double, double>> BPtr;
class BaseClass
{
public:
BPtr Func() = 0;
};
typedef boost::shared_pointer<S<double, std::tuple<double, double>>> Dptr;
class DerivedClass : public BaseClass
{
public:
DPtr Func() {}
}
理想情况下,我希望能够在派生类中返回覆盖typedef,但不能在C ++中执行此操作。
如何解决这个难题?
答案 0 :(得分:4)
首先,智能指针:他们没有共同的基类(就像vector<baseclass>
不是vector<derived>
的基类),因此协变返回类型不会起作用。
其次,即使你用原始指针替换智能指针,类模板的不同实例也不会共享一个共同的基础(如向量和智能指针),所以你运气不好。
请注意,类模板的不同实例化实际上可以相互派生,因此如果S<double,double>
是S<double,tuple<double,double>>
的基类,则可以使用协变返回,但这似乎是一种不稳定的方法。
总之,我认为您应该描述为什么您认为S<T,tuple<T,T>>
可以被视为S<T,T>
,这似乎是您代码中的基本假设。
答案 1 :(得分:2)
无论DerivedClass::Func
返回什么,都必须是BaseClass::Func
返回的子类型。否则,DerivedClass
显然 <{1}}的专业化。
是什么让你首先建立这种继承关系?没有它,您可以将BaseClass
的返回类型设为模板参数。
答案 2 :(得分:2)
首先,我认为你可能想让Base::Func()
成为virtual
成员函数。
class BaseClass
{
public:
virtual BPtr Func() = 0;
// ^^^ Missing
};
回复:
理想情况下,我希望能够在派生类中返回覆盖
typedef
但不能在C ++中执行此操作。
您可以覆盖派生类中的typedef
,但这并不一定使其成为virtual
成员函数的有效返回类型。
例如,如果我有:
struct Foo
{
typedef int return_type;
virtual return_type func() = 0;
};
struct Bar : Foo
{
typedef double return_type;
virtual return_type func() override { return 1.0; }
};
您应该收到编译错误。仅仅因为我在基类和派生类中都使用return_type
并不能使它们适合用作virtual
成员函数的返回类型。
重写实现中的返回类型可以是covariant type,而不是任何旧类型。 typedef
只是一个别名。这不是真正的类型。
回复:
如何解决这个难题?
您必须重新考虑您的退货类型。当基类中的返回类型为boost::shared_pointer<S<double, std::tuple<double, double>>>
时,您不能在派生类中使用boost::shared_pointer<S<double, double>>
作为返回类型。
答案 3 :(得分:0)
具有虚函数的(抽象)基类用于为派生类提供接口。根据派生类型,你不能让相同的函数返回不同的(更精确的非协变)事物,因为用户与基类有契约。
如果我有
Base * p = /* get whatever derived instance here */;
很可能我甚至无法判断指针后面隐藏了什么实际派生类型。
因此,如果Func
被声明为
boost::shared_ptr<S<double, double>> Func();
我希望它返回boost::shared_ptr<S<double, double>>
而不是取决于实际派生类型的东西。
原因很简单:如果添加一些派生类型会返回与我的代码不兼容的内容,那么它会破坏我的实现, out 界面会被更改。
如果S<double, std::tuple<double, double>>
来自S<double, double>
。
您无法使用typedef解决该限制,因为它们只是它们引用的类型的别名。使用类型using BPtr = boost::shared_ptr<S<double, double>>;
之类的typedef,此声明:
BPtr foo();
相当于
boost::shared_ptr<S<double, double>> foo();
如果重复使用typedef,那么输入就更少了。