forward declaration of inherited classes possible?

H

Heiner

Hi!

The following snippet


class B;

class A
{
public:
virtual B * getB();
};

class B
{
public:
virtual A * getA();
};


defines 2 classes. Both return pointer to each other. class A compiles
only, because B is forward declared (by class B;)

Now I would like to derive from them:


class DA : public A
{
public:
// virtual DB * getB(); <- does not compile
};

class DB : public B
{
public:
virtual DA * getA();
};


Unfortunately I can not get the getB() compiled. A simple forward
declaration (class DB;) gives a:

gcc main.cpp -o test
main.cpp:20: error: invalid covariant return type for `virtual DB* DA::getB()'
main.cpp:6: error: overriding `virtual B* A::getB()'

Question: Is there a forward declaration, which shows the compiler the
inheritance as well; something like a

class DB : public B;

(which does not work)?
 
B

Bob Hairgrove

Hi!

The following snippet


class B;

class A
{
public:
virtual B * getB();
};

class B
{
public:
virtual A * getA();
};


defines 2 classes. Both return pointer to each other. class A compiles
only, because B is forward declared (by class B;)

Now I would like to derive from them:


class DA : public A
{
public:
// virtual DB * getB(); <- does not compile
};

Class DA knows nothing about class B, much less about DB! DB could
inherit from anything ... but covariant return implies/requires that
the class declaring the function inherit from the original type being
returned, AFAIK [I couldn't find the appropriate passage in the
standard regarding covariant return types ... someone else able to
help here??]
class DB : public B
{
public:
virtual DA * getA();
};

Same here: class DB knows nothing about class A, nor about DA!
Unfortunately I can not get the getB() compiled. A simple forward
declaration (class DB;) gives a:

gcc main.cpp -o test
main.cpp:20: error: invalid covariant return type for `virtual DB* DA::getB()'
main.cpp:6: error: overriding `virtual B* A::getB()'

Question: Is there a forward declaration, which shows the compiler the
inheritance as well; something like a

class DB : public B;

(which does not work)?

There is no inheritance to show, hence no forward declaration.
 
V

Victor Bazarov

Heiner said:
The following snippet


class B;

class A
{
public:
virtual B * getB();
};

class B
{
public:
virtual A * getA();
};


defines 2 classes. Both return pointer to each other. class A compiles
only, because B is forward declared (by class B;)

Now I would like to derive from them:


class DA : public A
{
public:
// virtual DB * getB(); <- does not compile
};

class DB : public B
{
public:
virtual DA * getA();
};


Unfortunately I can not get the getB() compiled. A simple forward
declaration (class DB;) gives a:

gcc main.cpp -o test
main.cpp:20: error: invalid covariant return type for `virtual DB* DA::getB()'
main.cpp:6: error: overriding `virtual B* A::getB()'

Question: Is there a forward declaration, which shows the compiler the
inheritance as well; something like a

class DB : public B;

(which does not work)?

No. You're stuck with declaring 'getB' as returning a B*.

Or you could declare 'getDB', of course, and implement 'getB' which will
just call 'getDB'.

V
 
H

Heiner

Thanks for the response.

Class DA knows nothing about class B, much less about DB! DB could
inherit from anything ... but covariant return implies/requires that
the class declaring the function inherit from the original type being
returned, AFAIK [I couldn't find the appropriate passage in the

That is exactly my problem: I want to tell the compiler, that DB will
inherit from B!
Same here: class DB knows nothing about class A, nor about DA!

That's wrong. As the definition of A and DA was placed above the
definition of DB, DB knows all it needs. DB compiles without an error!

Did I make my problem more clear now?
 
V

Victor Bazarov

Bob said:
Class DA knows nothing about class B, much less about DB!

What do you mean? It knows everything about B. The definition of 'B'
is just above. It doesn't know about DB, but that's the essence of the
OP's question.
> DB could
inherit from anything ... but covariant return implies/requires that
the class declaring the function inherit from the original type being
returned, AFAIK [I couldn't find the appropriate passage in the
standard regarding covariant return types ... someone else able to
help here??]

Yes, that's what the OP is trying to do.
Same here: class DB knows nothing about class A, nor about DA!

What are you talking about? It knows everything about them, the are all
declared/defined right above.
There is no inheritance to show, hence no forward declaration.

It think you're way off base here.

V
 
H

Heiner

No. You're stuck with declaring 'getB' as returning a B*.

Or you could declare 'getDB', of course, and implement 'getB' which will
just call 'getDB'.

The first will result in several casts in the user code. If A is the
source of large class tree, the second will end up in getDDB, getDDDB, ...

Both are not very elegant, but if there is no better solution I will
probably choose the latter.

Thanks for your reply

Heiner
(e-mail address removed)
Remove the nospam to get my real address
 
G

Greg

Heiner said:
Hi!

The following snippet


class B;

class A
{
public:
virtual B * getB();
};

class B
{
public:
virtual A * getA();
};


defines 2 classes. Both return pointer to each other. class A compiles
only, because B is forward declared (by class B;)

Now I would like to derive from them:


class DA : public A
{
public:
// virtual DB * getB(); <- does not compile
};

class DB : public B
{
public:
virtual DA * getA();
};


Unfortunately I can not get the getB() compiled. A simple forward
declaration (class DB;) gives a:

gcc main.cpp -o test
main.cpp:20: error: invalid covariant return type for `virtual DB* DA::getB()'
main.cpp:6: error: overriding `virtual B* A::getB()'

Question: Is there a forward declaration, which shows the compiler the
inheritance as well; something like a

class DB : public B;

(which does not work)?

No. The compiler must know that that DB inherits from B in order for
DA::getB()'s return type to be a legal covariant return type. And only
DB's full declaration can show that DB derives from B.

Of course it is possible to declare the return type of DA::getB as B*
and have its implementation actually return a DB*. In most cases
returning the more abstract type is the better approach since fewer
dependencies are created. After all, why does the client have to know
that DA::getB returns a pointer to a DB instead of a B? One of the
benefits of polymorphism is that the client should not care about the
exact type of an object, as long as it conforms to a particular
interface. And if knowledge of the exact type is important to a client,
why doesn't the DA provide a getDB method instead of overriding
A::getB?

Greg
 
H

Heiner

Hi!

dependencies are created. After all, why does the client have to know
that DA::getB returns a pointer to a DB instead of a B? One of the

Just convenience. If I have a DB instance, I know, that getA will return
an DA. I do not have to cast or dyncast.
benefits of polymorphism is that the client should not care about the
exact type of an object, as long as it conforms to a particular

That would be the overridden getA as well!
interface. And if knowledge of the exact type is important to a client,
why doesn't the DA provide a getDB method instead of overriding A::getB?

Today I realized, that visual C does not allow any overriding of the
getA/getB. So I decided to do exactly this (although it doubles the number
of getters of this kind).

Thanks
 
G

Greg

Heiner said:
Hi!



Just convenience. If I have a DB instance, I know, that getA will return
an DA. I do not have to cast or dyncast.

Yes, but the client really isn't supposed to know that getA is really
returning a DA in some classes - much less be relying on it. Doing so
creates a dependency and weakens abstraction. The aim of polymorhpism
is to separate the interface from the details of its implementation,
and that can't be done if the client code is relying on the fact that
certain abstract instances have the type of certain concrete classes.
That would be the overridden getA as well!

Yes, but it will fix the compiler error. It's the DB* return type
(because it is different than the return type declared in the base
function), not overriding GetA itself that causes the error. Just make
sure that the implementation of GetA is in a source file and is not
inline, so that can know the actual return type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top