Override typedef in a derived class?

So, after much to answer my question, I finally gave up my Google skills.

I have a base class Base and a derived class Derived . I want to override the type in the Base class with one in the Derived class. Here is an example:

class Apple { public: Apple() { } // ... }; class Orange { public: Orange() { } // ... }; class Base { public: typedef Apple fruit; // ... virtual fruit func() { return Apple(); } }; class Derived : public Base { public: typedef Orange fruit; // ... fruit func() override { return Orange(); } // <-- Error C2555! }; 

This code does not work and it gives

 C2555 error ('Derived::func': overriding virtual function return type differs and is not covariant from 'Base::func'). 

Above was one of the solutions I tried. I also tried creating a virtual nested class in Base and overridden in Derived , and this also did not compile (it was also very dirty).

I also cannot get Apples and Oranges from the same base class to return a pointer / link to their parent class in Base and Derivatives . I need to physically return an instance of the object.

  • Is there a way to declare abstract typedefs?
  • If not, is there another solution that could achieve what I'm trying to do?
+6
source share
4 answers

First of all, look at this syntax:

 fruit func() override { return Orange(); } 

What is override ? There is no such keyword in C ++ 03. This is only in C ++ 11. Therefore, make sure you use a compiler that knows about this keyword.

Secondly, in the derived class fruit really Orange . Overriding typedef is not a problem. The problem is that Orange and Apple are not covariant. Deriving one from the other will make them covariant. In your case, you must get Orange from Apple to make it work.

Note that you must change the return type from fruit to fruit* or fruit& .

 class Orange : public Apple {}; //correct - your code will work class Apple : public Orange {}; //incorrect - your code will not work 

The idea is that in the base class, the return type should be a pointer / reference of the base type (which is equal to Apple ), and in the derived class, the return type can be a pointer / reference of the type Apple or any class that derives from it.

By the way, does that make sense? Withdraw Orange from Apple ?

What about the next design class?

 class Fruit {}; class Apple : public Fruit {}; class Orange : public Fruit {}; class Base { virtual Fruit* f(); }; class Derived : public Base { virtual Fruit* f(); }; 

No need to use typedef .

+6
source

From the very beginning, this makes no sense. A Derived should be used wherever Base is expected, so you should be able to do

 Base *foo = new Base(); Apple x = foo->func(); // this is fine Base *bar = new Derived(); Apple y = foo->func(); // oops... 

I think you need to think about a different design. It's unclear what your goal is, but I assume that you can either want Base be a class template with Fruit as the template parameter, or maybe you need to completely get rid of inheritance.

+1
source

You cannot do this, if you have a value object, you need to know what type it is. (This is one of the main differences between a statically typed language like C ++ and dynamically typed languages ​​like Ruby and Python.)

There are many ways around this. First, suppose Apple and Oragne have a common base class called Fruit . One solution is to dynamically select the object using new and return Fruit -pointer.

Another solution, instead of returning a value, your function could take a pointer or a reference to Fruit, which it could fill.

Another solution is to have some kind of container object inside which Apple or Orange will be located. That way you can return it.

0
source

The reported error tells you everything you need. This means that the type returned in the Derived method must be obtained from the type returned by the base method.

This is so that if the base method is called virtual, the returned object can be considered as returned by the base method.

In fact, you will need to return a pointer or link for this.

What you will need to do is define the new base Fruit class and get Apple and Orange from it.

Then << 24> return a Fruit* .

This will leave you with the problem of ensuring that Fruit* delete at some point.

With a bit more context, I suspect that (possibly subtle) templating is the solution you need, not inheritance.

0
source

Source: https://habr.com/ru/post/897202/


All Articles