在C ++中覆盖typedef

时间:2016-05-18 21:19:03

标签: c++

我有一个通用的结构

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 ++中执行此操作。

如何解决这个难题?

4 个答案:

答案 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,那么输入就更少了。