Friday, February 03, 2006

public inheritance broken

consider this:

class A
{
public:
void f();
void f(int x);
}

class B : public A
{
public:
void f(); // hides all A::f() overloads
}

you have an object
B b;
and you want to call the f(int x)
b.f(1);

normally you would think that since B inherits A, it inherits all the A functions, which is true, but not when for overloading.
the name f() declared in B class will override any base names. this includes the following case:

class A1
{
public:
void f();
}

class B1 : public A1
{
public:
int f; // hides all A1 'f'names
}

if you try to write the call:
b1.f();
you will get a compile error

as within a class, the names in a inheritance tree shoule be unique;

if you want to preserve the is-a relationship(a derived class should access all public inherited base class functionality) then you need to declare in the derived class the base functions by using 'using' declarator:

class B : public A
{public:
void f(); // hides all A 'f'names
using A::f; //OK, now we have the A::f(int x) within the B
}

b.f(1);

Note that 'using' works for the seeing in derived classes the overloads, it will not work for the 2nd case, when the base class is hiding a base class function by a member variale (because its not possible to have within the same class B 2 names f() and int f)

this is a problem described in Effective C++. Item 33. 'Avoid hiding inherited names'

No comments: