Member Function Invocation
When a member function is called with a derived class object, the compiler looks for that member in the derived class. If not found, it traverses the inheritance chain, checking each parent class for the existence of the member. The compiler utilizes the most-derived version of the function it finds.
Consider the following example:
#include <iostream>
class Base {
protected:
int m_value;
public:
Base(int value) : m_value(value) {}
void identify() const { std::cout << "I am a Base\n"; }
};
class Derived : public Base {
public:
Derived(int value) : Base(value) {}
};
int main() {
Base base{5};
base.identify();
Derived derived{7};
derived.identify();
return 0;
}
// Output
I am a Base
I am a Base
When derived.identify()
is called, the compiler searches for identify()
in the Derived
class, but since it is not defined there, it looks in the inherited class (Base
). As Base
has the identify()
function, it uses that one
Redefining Behaviors
If we define Derived::identify()
in the Derived
class, it will be used instead. This allows us to make functions work differently in the derived class by redefining them.
class Derived : public Base {
public:
Derived(int value) : Base(value) {}
void identify() const { std::cout << "I am a Derived\n"; }
};
Now, calling derived.identify()
results in:
I am a Base
I am a Derived
The derived function does not inherit the access specifier of the base function; it uses its own access specifier.
class Base {
private:
void print() const {
std::cout << "Base";
}
};
class Derived : public Base {
public:
void print() const {
std::cout << "Derived ";
}
};
Here, Derived::print()
is public, although Base::print()
is private
Adding to Existing Functionality
Sometimes, rather than completely replacing a base class function, we want to add additional functionality. In the example, Derived::identify()
hides Base::identify()
. To call the base version of the function and add extra functionality, use the scope qualifier:
class Derived : public Base {
public:
Derived(int value) : Base(value) {}
void identify() const {
Base::identify(); // Call Base::identify() first
std::cout << "I am a Derived\n"; // Then identify ourselves
}
};
Now, calling derived.identify()
produces:
I am a Base
I am a Derived