More about Inheritance

Function Hiding

In the following example, class Base has two overloaded member functions show() and show(int). Class Derived inherit from Base, and has a member function show().

class Base {
public:
    Base(int data = 10) : ma(data) {}
    void show() {
        cout << "Base::show()" << endl;
    }
    void show(int) {
        cout << "Base::show(int)" << endl;
    }
protected:
    int ma;
};

class Derived : public Base {
public:
    Derived(int data = 20) : Base(data), mb(data) {}
    void show() {
        cout << "Derived::show()" << endl;
    }
private:
    int mb;
};

Now in the main function we defined an object of class Derived. But when the function show(int) is called, an error occurs. Since Derived inherits show(int) from Base, why can't the compiler find it?

int main() {
    Derived d;
    d.show();   // Derived::show()
    d.show(10); // ERROR
    return 0;
}

Notice that when a member function is called, the compiler first search for it inside the derived class itself. Only if no definition is found within this scope does the compiler goes inside the base class. In this case, function Derived::show() hides the functions with the same name Base::show() and Base::show(int), which is called function hiding. To fix this, we may use d.Base::show(10) to call the corresponding function within the scope of Base.

Notice that function hiding refers to the hiding of functions with the same name defined in different scopes, which is very different from function overloading. Recall that the definition of function overloading is that, there are functions in the same scope whose names are the same, but their parameter lists are different. In the example above, Base::show() and Base::show(int) are a couple of overloaded functions.

Conversions of Base and Derived

Can a base class and a derived class be converted into each other? Let's see the following example:

int main() {
    Base b(10);
    Derived d(20);
    b = d;  // Yes
    d = b;  // No
    return 0;
}

Here we defined a Base object and a Derived object. Assume we have overloaded operator =, then it is valid to assign Derived to Base, but invalid to assign Base to Derived.

Object pointers are similar:

int main() {
    Base b(10);
    Derived d(20);
    Base *pb = &d;  // Yes
    pb->show(); // Base::show()
    Derived *pd = &b;   // No
    return 0;
}

Here we can let a Base pointer pointing to a Derived object, but not vice versa. Moreover, if we use a Base pointer which points to a Derived object, we can only access the members of Base. It is able to compile if we force a Derived pointer to point to a Base object using type conversion Derived *pd = (Derived *)&b, but it is unsafe, since there is not actually a Derived object, which may involve illegal memory access.

In all, in inheritance, only type conversion from bottom (base class) to top (derived class) is supported. Since derived class is a type of base class, which means that a base class is more generic, it make sense if we use something generic to point to something specific, but not the other wa

Last updated