By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,171 Members | 1,004 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,171 IT Pros & Developers. It's quick & easy.

Should this really be a compile error?

P: n/a
We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:

-------------------

class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.

}

class C
{

public:
void foo();

void foo(int i);

};

void C::foo(int i)
{
foo(); // Neither compiler gives an error here.

}

---------------------

Clearly it has something to do with the inheritance, but there is a
valid foo() call in the scope of B's foo(int). If we call "A::foo()"
instead, it works without complaint.

Jul 10 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a
ro*********@gmail.com wrote:
We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:
Dunno about the Sun compiler, bug g++ 2.95 is very old. You should upgrade
it.
class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.
They are coorect.
}

class C
{

public:
void foo();

void foo(int i);

};

void C::foo(int i)
{
foo(); // Neither compiler gives an error here.
They are again correct.
}

---------------------

Clearly it has something to do with the inheritance, but there is a
valid foo() call in the scope of B's foo(int). If we call "A::foo()"
instead, it works without complaint.
That's how it's supposed to be. A function in a derived class hides all
functions of the base class that have the same name. You must either
qualify it with A::foo() or add:

using A::foo;

to B's class definition.
Jul 10 '06 #2

P: n/a
In article <11**********************@m73g2000cwd.googlegroups .com>,
ro*********@gmail.com wrote:
We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:

-------------------

class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.

}
'foo()' is hidden in this scope, thus the error.

class B : public A {
using foo;
public:
void foo(int i);
};

Will stop the error.
Jul 10 '06 #3

P: n/a
"Rolf Magnus" <ra******@t-online.dewrote in message
news:e8*************@news.t-online.com...
ro*********@gmail.com wrote:
>We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:

Dunno about the Sun compiler, bug g++ 2.95 is very old. You should upgrade
it.
>class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.

They are coorect.
>}

class C
{

public:
void foo();

void foo(int i);

};

void C::foo(int i)
{
foo(); // Neither compiler gives an error here.

They are again correct.
>}

---------------------

Clearly it has something to do with the inheritance, but there is a
valid foo() call in the scope of B's foo(int). If we call "A::foo()"
instead, it works without complaint.

That's how it's supposed to be. A function in a derived class hides all
functions of the base class that have the same name. You must either
qualify it with A::foo() or add:

using A::foo;

to B's class definition.
Why is it supposed to be like that, out of interest? What's the problem
with/disadvantage of not hiding base functions with the same name?

Cheers,
Stu
Jul 10 '06 #4

P: n/a
In article <11**********************@m73g2000cwd.googlegroups .com>,
ro*********@gmail.com says...
We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:
They're right.
class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.
B::foo() hides A::foo() at this point. The compiler basically
searches back through the inheritance tree only as far as necessary
to find at least one function named foo. It then attempts to select
among any overloads of the name in that scope. If it can't find a
suitable overload it does NOT search further back through the
inheritance tree for more overloads -- it stops and gives an error.

As you've already noted, explicitly qualifying your call to A::foo()
allows the compiler to find the correct function. You can also use a
using declaration to get the compiler to treat A::foo() as if it was
in the same scope as B::foo():

class B : public A {
using A::foo;
public:
void foo(int i) {
foo();
}
};

Note, however, that this applies to A::foo in general -- if A
contains several overloads of foo(), it makes _all_ of them appear
local. It doesn't bring just one of those overloads into scope.

To summarize: functions with the same name at different scopes do NOT
overload each other. Rather, the name(s) at the inner scope hide the
name(s) at the outer scope, unless you take steps to prevent them
from begin hidden. As you'd expect, code like yours in which a
function in a derived class hides a function from a base class is
generally a poor idea. It can easily (and will often) lead to
unexpected results.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 10 '06 #5

P: n/a
Stuart Golodetz wrote:
[..] What's the
problem with/disadvantage of not hiding base functions with the same
name?
Name hiding transcends member functions. It's more general and making
it different for classes would overcomplicate things. Have you tried
looking in D&E? I just searched in Google Groups for <"name hiding"
why classand got enough discussions to keep one busy for a day (the
double quotes are needed, the 'class' word is supposed to keep non-C++
results out). Please don't ask us to start another beating of this
dead horse.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 10 '06 #6

P: n/a
"Victor Bazarov" <v.********@comAcast.netwrote in message
news:e8**********@news.datemas.de...
Stuart Golodetz wrote:
>[..] What's the
problem with/disadvantage of not hiding base functions with the same
name?

Name hiding transcends member functions. It's more general and making
it different for classes would overcomplicate things. Have you tried
looking in D&E? I just searched in Google Groups for <"name hiding"
why classand got enough discussions to keep one busy for a day (the
double quotes are needed, the 'class' word is supposed to keep non-C++
results out). Please don't ask us to start another beating of this
dead horse.

V
Ok, I'll check it out. I didn't realise it had been discussed before (I
probably should have looked first, thanks for pointing it out). "By all
means leave the poor beast alone", say I :)

Ta,
Stu
Jul 10 '06 #7

P: n/a
Rob

Jerry Coffin wrote:
In article <11**********************@m73g2000cwd.googlegroups .com>,
ro*********@gmail.com says...
We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:

They're right.
class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.

B::foo() hides A::foo() at this point. The compiler basically
searches back through the inheritance tree only as far as necessary
to find at least one function named foo. It then attempts to select
among any overloads of the name in that scope. If it can't find a
suitable overload it does NOT search further back through the
inheritance tree for more overloads -- it stops and gives an error.

As you've already noted, explicitly qualifying your call to A::foo()
allows the compiler to find the correct function. You can also use a
using declaration to get the compiler to treat A::foo() as if it was
in the same scope as B::foo():

class B : public A {
using A::foo;
public:
void foo(int i) {
foo();
}
};

Note, however, that this applies to A::foo in general -- if A
contains several overloads of foo(), it makes _all_ of them appear
local. It doesn't bring just one of those overloads into scope.

To summarize: functions with the same name at different scopes do NOT
overload each other. Rather, the name(s) at the inner scope hide the
name(s) at the outer scope, unless you take steps to prevent them
from begin hidden. As you'd expect, code like yours in which a
function in a derived class hides a function from a base class is
generally a poor idea. It can easily (and will often) lead to
unexpected results.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Thanks for the detail (thanks to everyone else who's replied, too!).

I understand why this is happening, now. I guess I was mostly
surprised because the size of the argument lists made the call to the
base class not ambiguous at all. But thinking about it, a standard
that said "names from a base class are usually hidden, unless they are
member functions and the access of them is not ambiguous" would be
pretty silly...

I looked in my "Annotated C++ Reference Manual", and there is a little
example, mostly related to unexpected argument conversion and overload
selection. The authors pointed out that if overload selection included
methods of base classes (even far up the chain), results could be very
unexpected.

Anyway, thanks again!

Rob

Jul 10 '06 #8

P: n/a
In article <dM********************@pipex.net>,
sg*******@dNiOaSl.PpAiMpPeLxE.AcSoEm says...

[ ... ]
Why is it supposed to be like that, out of interest? What's the problem
with/disadvantage of not hiding base functions with the same name?
First, it's inconsistent with the rest of the language. For example:

int my_f() {
float a;
{
int a;

a = 0.0;
}
}

Here, the assignment is clearly to the int, even though the float is
a better fit with the type of '0.0'.

Let's assume we changed the rules, and considered this an assignment
to the float. The second major problem can be seen by adding 'double
a' (or 'extern double a') outside the function. Now, even though the
function itself hasn't changed at all, the meaning of the assignment
has changed completely -- it's an assignment to a different variable
entirely.

This also interacts with another rule in C++: first it resolves
names, then it checks access. That means (for example) if you add a
variable in a base class, it participates in overload resolution the
same whether it's private, public or protected. IOW, adding almost
any name in the base class would potentially affect the results in
all derived classes, even if the base class name as private, so the
derived classes couldn't access it.

Such a change would make it nearly impossible to maintain the base
class. Nearly any change in the base class would require intimate
knowledge of all derived classes. A seemingly minor change in the
base class might completely change the meaning of code in some
derived classes, while rendering others completely illegal.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 10 '06 #9

P: n/a
"Jerry Coffin" <jc*****@taeus.comwrote in message
news:MP************************@news.sunsite.dk...
In article <dM********************@pipex.net>,
sg*******@dNiOaSl.PpAiMpPeLxE.AcSoEm says...

[ ... ]
>Why is it supposed to be like that, out of interest? What's the problem
with/disadvantage of not hiding base functions with the same name?

First, it's inconsistent with the rest of the language. For example:

int my_f() {
float a;
{
int a;

a = 0.0;
}
}

Here, the assignment is clearly to the int, even though the float is
a better fit with the type of '0.0'.

Let's assume we changed the rules, and considered this an assignment
to the float. The second major problem can be seen by adding 'double
a' (or 'extern double a') outside the function. Now, even though the
function itself hasn't changed at all, the meaning of the assignment
has changed completely -- it's an assignment to a different variable
entirely.

This also interacts with another rule in C++: first it resolves
names, then it checks access. That means (for example) if you add a
variable in a base class, it participates in overload resolution the
same whether it's private, public or protected. IOW, adding almost
any name in the base class would potentially affect the results in
all derived classes, even if the base class name as private, so the
derived classes couldn't access it.

Such a change would make it nearly impossible to maintain the base
class. Nearly any change in the base class would require intimate
knowledge of all derived classes. A seemingly minor change in the
base class might completely change the meaning of code in some
derived classes, while rendering others completely illegal.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Thanks, that makes sense now you put it like that :)

Cheers,
Stu
Jul 10 '06 #10

P: n/a
ro*********@gmail.com wrote:
We ran into this problem and I can't see why the compilers (Sun One
Studio 8 and g++ 2.95) think it's an error:

-------------------

class A
{
public:
void foo();

};

class B : public A
{
public:
void foo(int i);

};

void B::foo(int i)
{
foo(); // Both compilers give an error here.

}

class C
{

public:
void foo();

void foo(int i);

};

void C::foo(int i)
{
foo(); // Neither compiler gives an error here.

}

---------------------

Clearly it has something to do with the inheritance, but there is a
valid foo() call in the scope of B's foo(int). If we call "A::foo()"
instead, it works without complaint.
Others have answered this very well, but this is also in the FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-23.9

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jul 12 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.