Virtual function parameter variance

D

Dave

Hello all,

Quoting from page 24 of "The Boost Graph Library; User Guide and Reference
Manual":

"It turns out that by the contravariance subtyping rule, the parameter type
in the derived classes member function must be either the same type or a
base class of the type as the parameter in the base class."

Now please consider this code:

#include <iostream>

struct base_1 {};
struct derived_1: base_1 {};

struct base_2
{
virtual void foo(derived_1 *p) {std::cout << "base_2::foo()\n";}
};

struct derived_2: base_2
{
virtual void foo(base_1 *p) {std::cout << "derived_2::foo()\n";}
};

int main()
{
base_2 *ptr = new derived_2;
ptr->foo(new derived_1);
}

This outputs base_2::foo(). Why?

The quoted passage implies derived_2::foo() should override base_2::foo().
Clearly, it does not. Furthermore, I cannot find anything in the Standard
that indicates it should. So, I am clearly misinterpreting the quoted
passage. Can anybody explain to me what was meant in that passage?

Thank you,
Dave
 
B

Bob Hairgrove

Hello all,

Quoting from page 24 of "The Boost Graph Library; User Guide and Reference
Manual":

"It turns out that by the contravariance subtyping rule, the parameter type
in the derived classes member function must be either the same type or a
base class of the type as the parameter in the base class."

Now please consider this code:

#include <iostream>

struct base_1 {};
struct derived_1: base_1 {};

struct base_2
{
virtual void foo(derived_1 *p) {std::cout << "base_2::foo()\n";}
};

struct derived_2: base_2
{
virtual void foo(base_1 *p) {std::cout << "derived_2::foo()\n";}
};

int main()
{
base_2 *ptr = new derived_2;
ptr->foo(new derived_1);
}

This outputs base_2::foo(). Why?

The quoted passage implies derived_2::foo() should override base_2::foo().
Clearly, it does not. Furthermore, I cannot find anything in the Standard
that indicates it should. So, I am clearly misinterpreting the quoted
passage. Can anybody explain to me what was meant in that passage?

Thank you,
Dave

Unfortunately, it doesn't work the way you propose in C++.

Here is an interesting discussion about co- and contravariance WRT
C++. It is a little dated (1995), so maybe there is something new in
the works??

http://tinyurl.com/54f3d
 
B

Bob Hairgrove

[snip]

Sorry, it wasn't your proposal ... I got out my copy of the BGL and
looked up the quoted passage. It is confusing to me, too.

In context of what follows (namely, replacing inheritance and virtual
functions with non-member template functions to ensure type safety) I
interpret the quoted passage as a kind of "wishful thinking". The
example given BEFORE the passage illustrates something entirely
different, namely an attempt to use covariant parameter types (which
don't exist in C++ and hence the resulting error message).

But contravariant parameter types, although conceptually feasible,
also don't exist in C++ (yet??). That's the only sense I can make of
it. Note that the second example (ColorPoint2) uses a Point* as
parameter, which is the same type as the base class function "equal()"
takes. It wouldn't work if the derived class took a ColorPoint2* as an
argument (that would be contravariance) because the derived class
equal() would then hide the base class function.
 
B

Bob Hairgrove

On Sun, 08 Aug 2004 13:24:45 +0200, Bob Hairgrove

[snip]
But contravariant parameter types, although conceptually feasible,
also don't exist in C++ (yet??). That's the only sense I can make of
it. Note that the second example (ColorPoint2) uses a Point* as
parameter, which is the same type as the base class function "equal()"
takes. It wouldn't work if the derived class took a ColorPoint2* as an
argument (that would be contravariance) because the derived class
equal() would then hide the base class function.

Oops ... taking a ColorPoint2* in ColorPoint2::equal() would yet again
be covariance!

Contravariance would mean that Point::equal() would have to take a
more derived type pointer, and ColorPoint2::equal() a Point*.
Nevertheless, ColorPoint2::equal() would still hide Point::equal() if
the argument types aren't exactly the same.

(Slippery stuff, this contravariance ... no wonder it hasn't yet made
it into the language...)
 

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
474,144
Messages
2,570,823
Members
47,369
Latest member
FTMZ

Latest Threads

Top