Function Overriding in C++

A function is a block of statements that together performs a specific task by taking some input and producing a particular output. Function overriding in C++ is termed as the redefinition of base class function in its derived class with the same signature i.e. return type and parameters. It can be of both type: Compile Time and Runtime Polymorphism.

What is Function Overriding in C++?

Function overriding is a type of polymorphism in which we redefine the member function of a class which it inherited from its base class. The function signature remains same but the working of the function is altered to meet the needs of the derived class. So, when we call the function using its name for the parent object, the parent class function is executed. But when we call the function using the child object, the child class version will be executed.

Real-Life Example of Function Overriding

The best Real-life example of this concept is the Constitution of India. India took the political code, structure, procedures, powers, and duties of government institutions and set out fundamental rights, directive principles, and the duties of citizens of other countries and implemented them on its own; making it the biggest constitution in the world. 

Another Development real-life example could be the relationship between RBI(The Reserve Bank of India) and Other state banks like SBI, PNB, ICICI, etc. Where the RBI passes the same regulatory function and others follow it as it is.

Function Overriding

Types of Function Overriding in C++

Unlike other languages such as Java where function overriding is strictly done at compile time, C++ supports two types of function overriding:

  • Compile Time Overriding
  • Runtime Function Overriding

Compile Time Function Overriding

In compile time function overriding, the function call and the definition is binded at the compilation of the program. Due to this, it is also called early binding or static binding.

Syntax
class Parent {
    access_modifier :
  
        // overridden function
        return_type name_of_the_function() {}
};

class child : public Parent {
    access_modifier :
  
        // overriding function
        return_typename_of_the_function() {}
};

Example of Compile Time Function Overriding

C++
// C++ program to demonstrate compile time function overriding

#include <iostream>
using namespace std;

class Parent {
public:
    void w3wiki_Print()
    {
        cout << "Base Function" << endl;
    }
};

class Child : public Parent {
public:
    void w3wiki_Print()
    {
        cout << "Derived Function" << endl;
    }
};

int main()
{
    Child Child_Derived;
    Child_Derived.w3wiki_Print();
    return 0;
}

Output
Derived Function

Runtime Function Overriding using Virtual Function

Unlike other languages like Java, the function overriding in C++ can be performed at both compile time and runtime. In all the above examples, the call to the overridden function is resolved during compile time. It is also called early binding where the function call is binded to its definition during compilation.

Function overriding can also be performed at the runtime, which means that function call will be binded to its definition during runtime (also known as late binding or dynamic binding). This can be done with the help of virtual functions.

Syntax
class Base {
public:
    virtual func()
    {
        // definition
    }
};

class Derived : public Base {
public:
    func() override
    {
        // new definition
    }
};


Here, override keyword tells the compiler that the given overridden function should be declared as virtual in the parent class. It is a kind of double check as the program can compile without errors even if the function is not virtual. But then, it will be compile time polymorphism and we won’t get the desired behaviour of the function overriding.

Example of Runtime Function Overriding using Virtual Function

C++
// C++ Program to illustrate how to implement runtime
// function overriding using virtual function
#include <iostream>
using namespace std;

class Base {
public:
    // Declare the function as virtual to allow overriding
    // in derived classes
    virtual void display()
    {
        cout << "Display method of Base class" << endl;
    }

    // Virtual destructor to ensure proper cleanup of
    // derived class objects
    virtual ~Base() {}
};

class Derived : public Base {
public:
    // Override the display method
    void display() override
    {
        cout << "Display method of Derived class" << endl;
    }
};

int main()
{
    Base* basePtr;
    Derived derivedObj;

    // Point base class pointer to derived class object
    basePtr = &derivedObj;

    // Call the display function
    // This will call the display method of the Derived
    // class due to the virtual function mechanism
    basePtr->display();

    return 0;
}

Output
Display method of Derived class

Advantages of Runtime Function Overriding

The following are the main advantages of function overriding:

  • Methods are selected at runtime based on object type.
  • Common interfaces and implementations can be reused as we only need to implement the interface for base class.
  • Changes in base classes automatically affect derived classes.
  • Facilitates the implementation of design patterns different design patterns.
  • Client code interacts with base class interface, not specific implementations reducing the coupling.

Limitations of Runtime Function Overriding

While runtime function overriding provides numerous advantages, it also comes with certain limitations:

  • Virtual function calls are generally slower than non-virtual function calls due to the indirection involved in the virtual table lookup.
  • Implementing and maintaining polymorphic code can be more complex compared to simpler non-polymorphic code.
  • Virtual tables and virtual pointers add to the memory overhead, especially in large systems with many classes.
  • Errors related to function overriding (e.g., incorrect signatures) might only be detected at runtime, leading to potential bugs.

Examples of Function Overriding in C++

Example 1: C++ Program to Call Overridden Function From Derived Class

C++
// C++ program to demonstrate function overriding
// by calling the overridden function
// of a member function from the child class

#include <iostream>
using namespace std;

class Parent {
public:
    void w3wiki_Print()
    {
        cout << "Base Function" << endl;
    }
};

class Child : public Parent {
public:
    void w3wiki_Print()
    {
        cout << "Derived Function" << endl;

        // call of original function
        Parent::w3wiki_Print();
    }
};

int main()
{
    Child Child_Derived;
    Child_Derived.w3wiki_Print();
    return 0;
}

Output
Derived Function
Base Function

The output of Call Overridden Function From Derived Class

Example 2: C++ Program to Call Overridden Function Using Pointer

C++
// C++ program to access overridden function using pointer
// of Base type that points to an object of Derived class
#include <iostream>
using namespace std;

class Parent {
public:
    void w3wiki()
    {
        cout << "Base Function" << endl;
    }
};

class Child : public Parent {
public:
    void w3wiki()
    {
        cout << "Derived Function" << endl;
    }
};

int main()
{
    Child Child_Derived;

    // pointer of Parent type that points to derived1
    Parent* ptr = &Child_Derived;

    // call function of Base class using ptr
    ptr->w3wiki();

    return 0;
}

Output
Base Function

Example 3: C++ Program to Access of Overridden Function using Child Class Object

C++
// C++ program to access overridden function
// in main() using the scope resolution operator ::

#include <iostream>
using namespace std;

class Parent {
public:
    void w3wiki()
    {
        cout << "Base Function" << endl;
    }
};

class Child : public Parent {
public:
    void w3wiki()
    {
        cout << "Derived Function" << endl;
    }
};

int main()
{
     Child Child_Derived;
     Child_Derived.w3wiki();

    // access w3wiki() function of the Base class
     Child_Derived.Parent::w3wiki();
    return 0;
}

Output
Derived Function
Base Function

Access of Overridden Function to the Base Class

Function Overloading Vs Function Overriding

Function Overloading

Function Overriding

It falls under Compile-Time polymorphismIt can be both Compile Time or Runtime Polymorphism
A function can be overloaded multiple times as it is resolved at Compile timeA function cannot be overridden multiple times as it is resolved at Run time 
Can be executed without inheritanceCannot be executed without inheritance
They are in the same scopeThey are of different scopes.

To know more, you can refer to Function Overloading VS Function Overriding.