Derived methods hiding inherited methods

T

Tron Thomas

Under the right compiler the following code:

class Base
{
public:
virtual void Method(int){}
};

class Derived: public Base
{
public:
virtual void Method(float){}
};

will produce a warning such as:

'Derived::Method(float)' hides virtual function 'Base::Method(int)'

This warning can be eliminated by adding the statement:

using Base::Method;

to the derived class.

This issue with methods being hidden does not exist in other languages such as Java.
What is the reason that derived methods can potentially hide base methods in C++?
 
M

Mike Wahler

Tron Thomas said:
Under the right compiler the following code:

class Base
{
public:
virtual void Method(int){}
};

class Derived: public Base
{
public:
virtual void Method(float){}
};

will produce a warning such as:

'Derived::Method(float)' hides virtual function 'Base::Method(int)'

This warning can be eliminated by adding the statement:

using Base::Method;

to the derived class.

This issue with methods being hidden does not exist in other languages such as Java.
What is the reason that derived methods can potentially hide base methods
in C++?

The C++ feature called "function overloading".

-Mike
 
A

andre dajd

Tron Thomas said:
Under the right compiler the following code:

class Base
{
public:
virtual void Method(int){}
};

class Derived: public Base
{
public:
virtual void Method(float){}
};

will produce a warning such as:

'Derived::Method(float)' hides virtual function 'Base::Method(int)'

This warning can be eliminated by adding the statement:

using Base::Method;

to the derived class.

Yes, that's how C++ works, methods are hidden by names, not by full type.
The reason is purely practical. There is good explanation of why in
Effective C++ (I think), but the basic idea is that in C++ you can have
pretty complex inheritance patterns that could pull lots of overloaded
functions with almost same argumnets in the single leaf class, not really
"telling" the developer about it. He then can occasionally call a wrong
function, not knowing about it's existence somewhere deeply in the
inheritance lattice and then spend a lot of time debugging this problem

And using "using" directive is exactlhy the prescribed solution. It was
believed that to the developer explicitly pulling overloaded names that he
needs to the child classes will cost him less than navigating the classes
hierarchy in case of an error trying to identify what has gone wrong.
This issue with methods being hidden does not exist in other languages
such as Java.

That's because in Java all methods are virtual and there is no multiple
inheritance, hence the abovementioned tradeoff did not appear relevant to
Java designers.
What is the reason that derived methods can potentially hide base methods
in C++?

Rgds
d
 
A

andre dajd

Mike Wahler said:
Tron Thomas said:
Under the right compiler the following code:
[]

The C++ feature called "function overloading".

First, Java also has "function overloading". Second, "overloading" by
itself never hides anything. "Overriding" can, but not applicable in the
context.

Rgds,
d
 
G

Gary Labowitz

andre dajd said:
Yes, that's how C++ works, methods are hidden by names, not by full type.
The reason is purely practical. There is good explanation of why in
Effective C++ (I think), but the basic idea is that in C++ you can have
pretty complex inheritance patterns that could pull lots of overloaded
functions with almost same argumnets in the single leaf class, not really
"telling" the developer about it. He then can occasionally call a wrong
function, not knowing about it's existence somewhere deeply in the
inheritance lattice and then spend a lot of time debugging this problem

And using "using" directive is exactlhy the prescribed solution. It was
believed that to the developer explicitly pulling overloaded names that he
needs to the child classes will cost him less than navigating the classes
hierarchy in case of an error trying to identify what has gone wrong.


That's because in Java all methods are virtual and there is no multiple
inheritance, hence the abovementioned tradeoff did not appear relevant to
Java designers.

Also note that in Java the two functions are considered different if their
signatures are different, i.e. if the name plus the number and type of forma
l parameters differ. In this case if you called Method on the derived class
passing it an int (derived.Method(int)) you will run the inherited base
class Method; if you call Method on the derived class passing it a float
(derived.Method(float)) you will run the derived class Method. This is
called method overloading. Java will not convert the int call to a float and
call the derived class method. This is a major difference between C++ and
Java.
 
A

Andre Dajd

Gary Labowitz said:
andre dajd said:
Tron Thomas said:
Under the right compiler the following code: [snip]
This issue with methods being hidden does not exist in other languages
such as Java.

That's because in Java all methods are virtual and there is no multiple
inheritance, hence the abovementioned tradeoff did not appear relevant to
Java designers.

Also note that in Java the two functions are considered different if their
signatures are different, i.e. if the name plus the number and type of forma
l parameters differ.

Same in C++.
In this case if you called Method on the derived class
passing it an int (derived.Method(int)) you will run the inherited base
class Method; if you call Method on the derived class passing it a float
(derived.Method(float)) you will run the derived class Method. This is
called method overloading.

Again, same in C++, once you have brought the superclass' method into
the scope of the child; there will be no ambiguity in C++. But the
point here is different.

Overloading a function always means having a collection of
(different, obviousely) functions with same name, but different
signatures. Methods are special case of functions and you can
overload them by either extending a class or implementing several
overloaded members in the same class.

The only difference is what happens if you indeed overload a member in
a child class. Java will always differentiate it from all overloads
pulled from the superclass, overriding the one with same signature, if
it were present in the superclass. C++ will do same, once
specifically instructed by the developer by
"using" directive. C++ simply does not do it automatically for the
reasons I have already mentioned. Otherwise, the parent methods will
be hidden. This does not mean that the superclass method and
overriding method were considered "same". They are not same and
that's why the compiler issues the warning reported in the root
message. It's only the C++ default name resolution rule.
Java will not convert the int call to a float and
call the derived class method. This is a major difference between C++ and
Java.

Well, yes, Java is more strict in automatic conversion, but this is
not the point here. The point is that you may still bring several
overloaded methods into a leaf class; in Java you will have to do
repeated class inheritance while in C++ you can do it in one shot.
Then, if in the leaf class you may find yourself calling (by mistake)
a method from a superclass and then spend a lot of time figuring out
what went wrong. Note, that you will have to do that anyway even if
you do not overload a function in the child; you may still mix up the
parent members.

Apparently, this featuers comes from the time when nagivating thorugh
the class hierarchy was quite a complex task, which it was in the
absense of Javadoc or Doxygen or advanced IDEs, or anything else
alike. So, this C++ feature simply warns the developer about a
possible problem.

d
 
T

Tom Widmer

Under the right compiler the following code:

class Base
{
public:
virtual void Method(int){}
};

class Derived: public Base
{
public:
virtual void Method(float){}
};

will produce a warning such as:

'Derived::Method(float)' hides virtual function 'Base::Method(int)'

This warning can be eliminated by adding the statement:

using Base::Method;

to the derived class.

This issue with methods being hidden does not exist in other languages such as Java.
What is the reason that derived methods can potentially hide base methods in C++?

IIRC it's mainly to protect against the addition of new functions in
base classes silently changing the meaning of code using derived
classes. I suggest you read "The Design and Evolution of C++" by
Stroustrup.

Note that Java can be more dangerous than C++ to use for large scale
software development (projects with millions of LOC) because it wasn't
designed in such a way as to have changes in base classes have minimal
silent impact on derived classes. In Java, adding a new base class
function can silently change the meaning of code using a derived
class; the base class author may know nothing at all about this
derived class.

Tom
 
G

Gary Labowitz

Tom Widmer said:
On 8 Nov 2004 15:46:22 -0800, (e-mail address removed) (Tron Thomas)
wrote:
Note that Java can be more dangerous than C++ to use for large scale
software development (projects with millions of LOC) because it wasn't
designed in such a way as to have changes in base classes have minimal
silent impact on derived classes. In Java, adding a new base class
function can silently change the meaning of code using a derived
class; the base class author may know nothing at all about this
derived class.

I'd be interested in your explanation of this. If a new method is added to a
base class, how does that affect a derived class that doesn't even know
about it? There are probably lots of people using derived classes (that's
ALL of them in Java) that don't know the clone( ) method exists and don't
care. If you see something here I don't I'd appreciate your giving an
example.
 
P

Pete Becker

Gary said:
I'd be interested in your explanation of this. If a new method is added to a
base class, how does that affect a derived class that doesn't even know
about it? There are probably lots of people using derived classes (that's
ALL of them in Java) that don't know the clone( ) method exists and don't
care. If you see something here I don't I'd appreciate your giving an
example.

struct Base
{
};

struct Derived : Base
{
void f(int);
};

Derived d;
d.f(3.0); // calls Derived::f(int);

Now someone adds f(double) to Base, and d.f(3.0) no longer calls
Derived::f(int).
 
G

Gary Labowitz

Pete Becker said:
struct Base
{
};

struct Derived : Base
{
void f(int);
};

Derived d;
d.f(3.0); // calls Derived::f(int);

Now someone adds f(double) to Base, and d.f(3.0) no longer calls
Derived::f(int).

Oh, I'm sorry, Peter. I thought the comment was about Java. I understand
this problem with C++. Thanks, though.
 
T

Tom Widmer

Oh, I'm sorry, Peter. I thought the comment was about Java. I understand
this problem with C++. Thanks, though.

The above was a demonstration of a problen that C++ *doesn't* have,
but Java does. In the above in C++, d.f(3.0) always calls Derived::f,
even if f(double) is added to Base, since Derived::f hides Base::f (if
there is one). To clarify, here's the Java that demonstrates the
problem:

class Base
{
}

class Derived extends Base
{
public void f(double d)
{
}
}

Derived d = new Derived();
d.f(3);

The above now calls Derived.f, but if you add f(int) to the base
class, suddenly the meaning of that code will silently change.
Basically the problem relates to name clashes between the method names
of base classes and their derived classes.

Tom
 

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,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top