COVARIANT RETURN TYPE

Started by
6 comments, last by TGE 12 years, 10 months ago
Hy everyone !

Here is a peace of code that leads to the following error when compiling : invalid covariant return type for ‘virtual List* Elem::list()’

[source]class AbstractList;

class AbstractElem
{
public :
virtual AbstractList* list() = 0;
protected :
AbstractElem() {};
};

class List;

class Elem : public AbstractElem
{
public :
Elem() :
AbstractElem()
{};
virtual List* list()
{
return _list;
}
protected :
List* _list;
};

class AbstractList
{
public :
virtual AbstractElem* elem() = 0;
protected :
AbstractList() {};
};

class List : public AbstractList
{
public :
List() :
AbstractList()
{}

virtual Elem* elem()
{
return _e;
}
protected :
Elem* _e;
};

int main()
{
return 0;
}[/source]

The thing that I don't understand is why I only get this error for the list() function but not for the elem() function !

Could anyone explain me the difference ?

Thanks.
Advertisement
It is complaining that you changed the return type of a virtual function to a type that is incompatible with the base classes's return type. You either have to return the exact same type, or a class that is derived from that type.

In this case you are changing from a return type of AbstractList* to List*. This should be fine, except that since you are using a pre-declaration, it looks like it doesn't know that List* is derived from anything until much later in your code. You may need to break the classes out into separate headers or try moving the AbstractList and List definition before Elem's definition.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

Thanks for the answer ! I already tried this, separating into Elem.h and List.h and here is what I get as an error :

In file included from List.h:4,
from covariant.cpp:1:
Elem.h:9: error: ISO C++ forbids declaration of ‘AbstractList’ with no type
Elem.h:9: error: ‘AbstractList’ declared as a ‘virtual’ field
Elem.h:9: error: expected ‘;’ before ‘*’ token
Elem.h:22: error: ISO C++ forbids declaration of ‘List’ with no type
Elem.h:22: error: ‘List’ declared as a ‘virtual’ field
Elem.h:22: error: expected ‘;’ before ‘*’ token
Elem.h:27: error: expected `;' before ‘protected’
Elem.h:28: error: ISO C++ forbids declaration of ‘List’ with no type
Elem.h:28: error: expected ‘;’ before ‘*’ token


Using class Elem; and class List; instead of #include in the header file leads to the same error than before...

Any idea ?

[source lang="cpp"]#ifndef _ELEM_
#define _ELEM_

#include "List.h"

class AbstractElem
{
public :
virtual AbstractList* list() = 0;

protected :
AbstractElem() {};
};

class Elem : public AbstractElem
{
public :
Elem() :
AbstractElem()
{};

virtual List* list()
{
return _list;
}

protected :
List* _list;
};

#endif[/source]

[source lang="cpp" ]#ifndef _LIST_
#define _LIST_

#include "Elem.h"

class AbstractList
{
public :
virtual AbstractElem* elem() = 0;

protected :
AbstractList() {};
};

class List : public AbstractList
{
public :
List() :
AbstractList()
{}

virtual Elem* elem()
{
return _e;
}

protected :
Elem* _e;
};


#endif[/source]
Why are you using an inheritance hierarchy for containers in C++? Its totally unnecessary and underperformant, and there are superior options such as the standard C++ containers (in design as well as implementation).
That was just an example. I'm not trying to develop a new container, the names are arbitrary, I just though it would be easier than using A, B or C as a class name ;)
I've got this error in a much more complex example and tried to find a more simple one.

I just want to understand why I had a compilation error in re-implemented list() but not for elem() !
What you are facing now are circular dependencies.

About the only way I can see you solving it would be to replace the Elem* 's in List with AbstractElem* 's in the List definition and List* 's with AbstractList* 's in Elem's definition.

That being said, I would look at what rip-off said. You might give some more details on what you are trying to accomplish.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]


I just want to understand why I had a compilation error in re-implemented list() but not for elem() !


Ultimately the answer is that the pre-declaration of List didn't establish it as derived class of AbstractList only that there was a class named List ; but by the time you defined elem(), you had completely defined Elem as a dervied class of AbstractElem.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]


About the only way I can see you solving it would be to replace the Elem* 's in List with AbstractElem* 's in the List definition and List* 's with AbstractList* 's in Elem's definition.


I think I'm gonna try this way. Thanks !

This topic is closed to new replies.

Advertisement