469,623 Members | 1,935 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,623 developers. It's quick & easy.

Virtual function parameter variance


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
Jul 22 '05 #1
3 5060
On Sat, 7 Aug 2004 23:38:14 -0700, "Dave" <be***********@yahoo.com>
wrote:

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

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #2
On Sun, 08 Aug 2004 12:29:21 +0200, Bob Hairgrove
<wouldnt_you_like@to_know.com> wrote:
On Sat, 7 Aug 2004 23:38:14 -0700, "Dave" <be***********@yahoo.com>
wrote:

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."

[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.

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #3
On Sun, 08 Aug 2004 13:24:45 +0200, Bob Hairgrove
<wouldnt_you_like@to_know.com> wrote:

[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...)

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

6 posts views Thread by Vajira | last post: by
8 posts views Thread by Floogle | last post: by
12 posts views Thread by mohan | last post: by
2 posts views Thread by Markus Dehmann | last post: by
10 posts views Thread by =?Utf-8?B?Y2FybG0=?= | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.