Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redefining a typedef in derived class?

So after searching a lot for an answer to my question, I finally gave up on my Google skills.

I have an base class Base, and a derived class Derived. I want to override a type in the Base class with one in the Derived class. Here's 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 doesn't work, and it gives a

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

Above was one of solutions I tried. I also tried creating a virtual nested class in the Base, and redefined in Derived, and that didn't compile also (it was also very messy).

I also can't derive Apples and Oranges from the same base class to return pointer/reference to their parent class in Base and Derived. I need to physically return an instance of the object.

  1. Is there any way I can declare abstract typedefs?
  2. If not, is there any other solution that could achieve what I'm trying to do?
like image 560
Zeenobit Avatar asked Sep 13 '11 06:09

Zeenobit


People also ask

How do I override typedef?

You can override (localize) typedef by moving them into the class. But C++ requires virtual functions to have the same signature and the return type is part of the signature.

What do you mean by function redefining in C++?

A redefined function is a method in a descendant class that has a different definition than a non-virtual function in an ancestor class.

Can we use typedef in class?

Classes and structures can have nested typedefs declared within them.

What is the difference between an overridden method and a redefined method?

Overriding: The method in the ancestor class is virtual. A new implementation overrides the virtual one. Redefining: The method in the ancestor class isn't virtual. Therefore the compiler has to choose which method gets used at compiletime.


1 Answers

First of all, look at this syntax :

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

What is override? In C++03, there is no such keyword. It's only in C++11. So make sure that you're using a compiler which knows of this keyword.

Second, in the derived class, fruit is indeed Orange. Redefining the typedef is not a problem. The problem is, Orange and Apple are not covariant type. Deriving one from another will make them covariant. In your case, you've to derive Orange from Apple in order to make it work.

Note you've to change the return type from fruit to either 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, in the base class, the return type should be pointer/reference of base type (which is Apple), and in the derived class, the return type can be pointer/reference of type Apple or any class which derives from it.

By the way, does this make sense? Deriving Orange from Apple?

How about the following class-design?

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.

like image 121
Nawaz Avatar answered Oct 05 '22 16:10

Nawaz