Overriding virtual functions problem

A

AGoTH

class A {
public:
virtual void foo(int b) {}
virtual void foo(char* b) {}
};

class B : public A{
virtual void foo(int b) {}
};


void
foo()
{
B* b;
b->foo("tgre");
}

this code does not compile, neither in Visual C++ nor in Codewarrior.
Does someone know why ?

Aymeric Bard.
 
J

Jakob Bieling

AGoTH said:
class A {
public:
virtual void foo(int b) {}
virtual void foo(char* b) {}
};

class B : public A{
virtual void foo(int b) {}
};


void
foo()
{
B* b;
b->foo("tgre");
}

this code does not compile, neither in Visual C++ nor in Codewarrior.
Does someone know why ?


The 'foo(int)' in B hides 'foo(char*)' of A and overloads 'foo(int)'
Define an overload for 'foo(char*)' in B, where you just forward the call to
'A::foo(int)'.

hth
 
K

Karl Heinz Buchegger

Jakob said:
The 'foo(int)' in B hides 'foo(char*)' of A and overloads 'foo(int)'
Define an overload for 'foo(char*)' in B, where you just forward the call to
'A::foo(int)'.

or add a using directive to class B

class B : public A
{
using A::foo;
 
K

Karl G. Merkley

Jakob said:
call to




This one is actually much nicer! Thanks for the hint!
I was just about to ask this same question! I'm still not completely clear on
why 'foo(int)' in B hides 'foo(char*)' in A. I would have thought that the name
mangling would have created completely different symbols for 'foo(int)' and
'foo(char*)' and thus 'foo(char*)' would not be hidden.

Karl
 
K

Kevin Goodsell

Jakob said:
The 'foo(int)' in B hides 'foo(char*)' of A and overloads 'foo(int)'
Define an overload for 'foo(char*)' in B, where you just forward the call to
'A::foo(int)'.

I think you meant to say:

The 'foo(int)' in B hides 'foo(char*)' of A and _overrides_ 'foo(int)'.
Define an overload for 'foo(char*)' in B, where you just forward the
call to _'A::foo(char*)'_.

Of course, a using declaration is an easier solution.

This is a pretty common question, and the basic answer is "function
overload resolution does not cross inheritance boundaries."

-Kevin
 
J

Jakob Bieling

Kevin Goodsell said:
I think you meant to say:

The 'foo(int)' in B hides 'foo(char*)' of A and _overrides_ 'foo(int)'.
Define an overload for 'foo(char*)' in B, where you just forward the
call to _'A::foo(char*)'_.

Uh yes, got confused by all the overriding and hiding and overloading ;)

Thanks for the correction!
 
V

Victor Bazarov

NeilF said:
[...]
Unless it's explained in the FAQ, perhaps you could take the time to explain
why hiding related member functions is useful. Perhaps it's something to do
with avoiding program misbehavior caused by implicit parameter casting?

I am fairly sure that the rationale behind name hiding has been already
given in one form or another, and if you look for it, you'll find it.
No, I don't have any links off the top of my head. And it's been some
time since I opened D&E ("Design and Evolution of C++" by Stroustrup)
last time, I just don't remember if there is some description there.

Name hiding is fundamental and is not C++ specific. In C, if you declare
a variable in a block, it would hide another variable with the same name
in the enclosing block. It's been like this for ages.

I believe that when the time came to define the relationship of derived
classes' scopes, Bjarne had only two possible outcomes: either make class
scopes follow the normal nested scopes line or make them an exception.
Perhaps making them an exception promised more unnecessary complexity and
would be more difficult to explain and justify. I don't know for sure.

Try asking in comp.std.c++. Most of Standard Committee people frequent
that newsgroup, many must remember why name hiding was extended onto class
members (or have some links handy). It's actually much better place to
ask the "why" questions than comp.lang.c++. Here we mostly talk "how".

Victor
 
J

Jerry Coffin

[ ... ]
I believe that when the time came to define the relationship of derived
classes' scopes, Bjarne had only two possible outcomes: either make class
scopes follow the normal nested scopes line or make them an exception.
Perhaps making them an exception promised more unnecessary complexity and
would be more difficult to explain and justify. I don't know for sure.

I the D&E, Bjarne also mentions that if you looked in the base class, it
could rather unexpectedly change how programs worked. Just for example,
assume a base class has f(long) and a derived class has f(long). If you
call f(1), it basically invokes derived::f(1L) (i.e. invokes the derived
version of f, converting the argument to a long in the process.

Now, if it looked in the base class as well, then adding f(int) to the
base would mean that the client code would now invoke base::f(1). A
seemingly rather innocent change in the base class might make wholesale
changes in code that doesn't use the base class directly at all.

In particular, while the current situation causes something new users
often find unexpected, it's (generally) something that becomes obvious
when you first write the client code -- typically, it won't compile at
all, because the code attempts to call a function that's no longer
visible.

The alternative is rather the opposite: it can silently change behavior
long after code is written, and many compilers would probably let you do
it without so much as a peep of warning either (though if it's a major
change in behavior, the design is probably suspect).
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top