"using" declaration

  • Thread starter Christian Christmann
  • Start date
C

Christian Christmann

Hi,

I'm reading "C++ Coding Standards" by Herb Sutter.
On page 67 there's an example which I don't understand:
---------------------------------
class Base{// ...
virtual void Foo(int);
virtual void Foo(int, int);
void Foo(int, int, int);
};

class Derived : public Base { // ...
virtual void Foo(int); // overrides Base::Foo(int), but hides the others
};

Derived d;
d.Foo(1); // ok
d.Foo(1,2); // error
d.Foo(1,2,3); // error
-----------------------------------

I don't understand why the functions "virtual void Foo(int, int)" and
"void Foo(int, int, int)" are hidden by Derived::Foo(int) ?
My opinion was that a derived class is always inheriting all functions
of a base class and can additionally override them for a specific purpose
like Foo(int).


To bring the other Base::Foo overloads into scope Sutter is using the
statement

using Base::Foo;

within the Derive class.


Thank you for your answers.

Greeting,
Chris
 
K

Karl Heinz Buchegger

Christian said:
Hi,

I'm reading "C++ Coding Standards" by Herb Sutter.
On page 67 there's an example which I don't understand:
---------------------------------
class Base{// ...
virtual void Foo(int);
virtual void Foo(int, int);
void Foo(int, int, int);
};

class Derived : public Base { // ...
virtual void Foo(int); // overrides Base::Foo(int), but hides the others
};

Derived d;
d.Foo(1); // ok
d.Foo(1,2); // error
d.Foo(1,2,3); // error
-----------------------------------

I don't understand why the functions "virtual void Foo(int, int)" and
"void Foo(int, int, int)" are hidden by Derived::Foo(int) ?
My opinion was that a derived class is always inheriting all functions
of a base class and can additionally override them for a specific purpose
like Foo(int).

It is a direct consequence of how the compiler looks up a function.
First it searches the class hierarchy for a class which has that function.

In your specific example, when you write
d.foo(1,2);

the compiler looks up the type of d. It is Derived. Thus it looks into class
Derived, if there are one or more functions called Foo(). If there are, proceed
to the next step. If there are no, then look up the base class and try there.
Note: The number and type of the arguments is irrelevant in this step. The compiler
searches for the functions just by looking at their names!

The next step is to decide which function to choose based on the number of arguments
and their types in the set of found functions of the previous step.
In your specific case, the set of those functions contains only 1 function, since Derived
contains only 1 function called 'Foo'. The compiler sees, that Foo takes only one argument
but the call specifies 2 parameters. Thus the error message.
Note: If no argument match can be made, the compiler stops! It doesn't look for other
functions in the base class(es).

That's called hiding: A function in a derived class hides all functions with the same
name in the base class(es).
To bring the other Base::Foo overloads into scope Sutter is using the
statement

using Base::Foo;

within the Derive class.

That's one way to work around function hiding.
 
C

Chris Theis

Christian Christmann said:
Hi,

I'm reading "C++ Coding Standards" by Herb Sutter.
On page 67 there's an example which I don't understand:
---------------------------------
class Base{// ...
virtual void Foo(int);
virtual void Foo(int, int);
void Foo(int, int, int);
};

class Derived : public Base { // ...
virtual void Foo(int); // overrides Base::Foo(int), but hides the others
};

Derived d;
d.Foo(1); // ok
d.Foo(1,2); // error
d.Foo(1,2,3); // error
-----------------------------------

I don't understand why the functions "virtual void Foo(int, int)" and
"void Foo(int, int, int)" are hidden by Derived::Foo(int) ?
My opinion was that a derived class is always inheriting all functions
of a base class and can additionally override them for a specific purpose
like Foo(int).


To bring the other Base::Foo overloads into scope Sutter is using the
statement

using Base::Foo;

within the Derive class.


Thank you for your answers.

Greeting,
Chris

Regarding the issue of function hiding it does not really matter whether the
function is declared virtual or not. See section 23.7 of the FAQ.

HTH
Chris
 
A

Alf P. Steinbach

* Christian Christmann:
I'm reading "C++ Coding Standards" by Herb Sutter.
On page 67 there's an example which I don't understand:
---------------------------------
class Base{// ...
virtual void Foo(int);
virtual void Foo(int, int);
void Foo(int, int, int);
};

class Derived : public Base { // ...
virtual void Foo(int); // overrides Base::Foo(int), but hides the others
};

Derived d;
d.Foo(1); // ok
d.Foo(1,2); // error
d.Foo(1,2,3); // error

It's a more-or-less arbitrary language design decision; there are arguments
for, and arguments against.

The hiding ensures that calls to Foo in Derived won't inadvertently become
bound to inherited Foo implementations; in particular, with the hiding in
effect, which implementation a call to Foo in Derived is bound to cannot be
changed by adding new functions to Base (oops, I added a Base function and
suddenly Derived stopped working), part of the "fragile base class" problem.

This gives control to the Derived programmer, but it also means that the
"Derived is a kind of Base" rule is broken. I think the AKO rule is _much_
more important than "fragile base class", and the hiding is at best only a
very partial solution to that, and nobody finds the hiding very intuitive
(well, nobody I know). But then that's how it is with a lot of things.
 
J

Jacques Labuschagne

Christian said:
I don't understand why the functions "virtual void Foo(int, int)" and
"void Foo(int, int, int)" are hidden by Derived::Foo(int) ?
My opinion was that a derived class is always inheriting all functions
of a base class and can additionally override them for a specific purpose
like Foo(int).

I'm afraid I don't know why it was done this way, but it is indeed the
case. Section 13.2/1 has this example:

class B{
public:
int f(int);
};

class D: public B{
public:
int f(char*);
};

Here D::f(char*) hides B::f(int) rather than overloading it.

void h(D* pd)
{
pd->f(1); // error: D::f(char*) hides B::f(int)
pd->B::f(1); // OK
pd->f("Ben"); // OK, calls D::f
}

- end example.

Paragraph 10.2/2 is probably relevant, but I couldn't quite decipher it.

Regards,
Jacques.
 

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
474,204
Messages
2,571,064
Members
47,672
Latest member
svaraho

Latest Threads

Top