简体   繁体   English

在C ++中覆盖typedef

[英]Overriding typedefs in C++

I have a generic struct 我有一个通用的结构

template<typename X, typename Y>
struct S
{

};

Then there is an abstract class which returns shared pointer to above struct in a pure virtual function. 然后有一个抽象类,它在纯虚函数中返回上面struct的共享指针。 One of the derived classes also implements this function but needs to return pointer to S with different instantiated type: 其中一个派生类也实现了这个函数,但是需要使用不同的实例化类型返回指向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() {}
}

Ideally I would like to be able to return an override typedef in the derived class but can't do that in C++. 理想情况下,我希望能够在派生类中返回覆盖typedef,但不能在C ++中执行此操作。

How do I fix this dilemma? 我该如何解决这个难题?

Firstly, the smart pointers: They don't have a common baseclass (just as vector<baseclass> is not a baseclass of vector<derived> ), so covariant return types won't work. 首先,智能指针:它们没有共同的基类(就像vector<baseclass>不是vector<derived>的基类),因此协变返回类型将不起作用。

Secondly, even if you replaced the smart pointers with raw pointers, different instantiations of a class template don't share a common base either (like vector and smart pointers), so you're out of luck. 其次,即使你用原始指针替换了智能指针,类模板的不同实例也不会共享一个共同的基础(如向量和智能指针),所以你运气不好。

Note that different instantiations of class templates can actually derive from one another, so if S<double,double> was a baseclass for S<double,tuple<double,double>> , you could use covariant returns, but that seems like a wonky approach. 请注意,类模板的不同实例化实际上可以相互派生,所以如果S<double,double>S<double,tuple<double,double>>的基类,则可以使用协变返回,但这看起来像一个不稳定的做法。

In summary, I think you should describe why you think that an S<T,tuple<T,T>> could be treated like an S<T,T> , which seems the underlying assumption in your code. 总而言之,我认为您应该描述为什么您认为S<T,tuple<T,T>>可以被视为S<T,T> ,这似乎是代码中的基本假设。

Whatever DerivedClass::Func returns must be a subtype of what BaseClass::Func returns. 无论DerivedClass::Func返回什么,必须是BaseClass::Func返回的子类型。 Otherwise, DerivedClass is obviously not a specialization of BaseClass . 否则, DerivedClass显然不是 BaseClass

What makes you build this inheritance relationship in the first place? 是什么让你首先建立这种继承关系? Without it, you could just make the return type of Func a template parameter. 没有它,您可以只将Func的返回类型作为模板参数。

First of all, I think you probably meant to make Base::Func() a virtual member function. 首先,我认为你可能想让Base::Func()成为一个virtual成员函数。

class BaseClass
{
  public:
    virtual BPtr Func() = 0;
 // ^^^ Missing 
};

Re: 回覆:

Ideally I would like to be able to return an override typedef in the derived class but can't do that in C++. 理想情况下,我希望能够在派生类中返回覆盖typedef ,但不能在C ++中执行此操作。

You can override the typedef in the derived class but that does not necessarily make it a valid return type of the virtual member function. 您可以覆盖派生类中的typedef ,但这并不一定使其成为virtual成员函数的有效返回类型。

For instance, if I have: 例如,如果我有:

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; }
};

You should get a compiler error. 您应该收到编译器错误。 Just because I use return_type in both the base class and the derived class does not make them suitable to be used as the return type of the virtual member function. 仅仅因为我在基类和派生类中都使用了return_type ,这使得它们不适合用作virtual成员函数的返回类型。

The return type in an overridden implementation can be covariant type , not any old type. 重写实现中的返回类型可以是协变类型 ,而不是任何旧类型。 A typedef is just an alias. typedef只是一个别名。 It's not a true type. 这不是真正的类型。

Re: 回覆:

How do I fix this dilemma? 我该如何解决这个难题?

You'll have to rethink your return types. 您必须重新考虑您的退货类型。 You cannot use boost::shared_pointer<S<double, std::tuple<double, double>>> for the return type in the derived class when the return type in the base class is boost::shared_pointer<S<double, double>> . 当基类中的返回类型为boost::shared_pointer<S<double, double>>时,不能对派生类中的返回类型使用boost::shared_pointer<S<double, std::tuple<double, double>>> boost::shared_pointer<S<double, double>>

An (abstract) base class with virtual functions is used to provide the interface for the derived classes. 具有虚函数的(抽象)基类用于为派生类提供接口。 You cannot have the same function return different (more precisily non-covariant) things depending on the derived type because the user has a contract with the base class. 根据派生类型,您不能使用相同的函数返回不同的(更精确的非协变)事物,因为用户与基类具有契约。

If I have a 如果我有

Base * p = /* get whatever derived instance here */;

it might very well be the case that I cannot even tell what actual derived type is hidden behind the pointer. 很可能就是我甚至无法分辨指针背后隐藏的实际派生类型。

Therefore, if Func is declared as 因此,如果Func被声明为

boost::shared_ptr<S<double, double>> Func();

I'd expect it to return boost::shared_ptr<S<double, double>> and not something that depends on the actual derived type. 我希望它返回boost::shared_ptr<S<double, double>>而不是依赖于实际派生类型的东西。

The reason is simple: If some derived type would be added that returns something that is incompatible with my code it would break my implementation with out the interface being changed at all. 原因很简单:如果某些派生类型将被添加返回的东西,是我的代码,将打破我的实现与接口所发生任何变化不兼容。

It would work however, if S<double, std::tuple<double, double>> would derive from S<double, double> . 但是,如果S<double, std::tuple<double, double>>将从S<double, double>派生,它将起作用。

You cannot get around that restriction with typedefs because they are just alias names for the types they refer to. 您无法使用typedef解决该限制,因为它们只是它们引用的类型的别名。 With a typedef like using BPtr = boost::shared_ptr<S<double, double>>; 使用类似于using BPtr = boost::shared_ptr<S<double, double>>;的typedef using BPtr = boost::shared_ptr<S<double, double>>; , this declaration: ,这个声明:

BPtr foo();

is equivalent to 相当于

boost::shared_ptr<S<double, double>> foo();

it is just less typing involved if the typedef is used repeatedly. 如果重复使用typedef,那么只需要更少的输入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM