Function overriding is an inheritance feature that allows a derived class to redefine a virtual function of the base class. It enables the same function call to behave differently depending on the object, making it a key feature of runtime polymorphism.
- Provides specialized behavior for derived class objects.
- Promotes code reuse and flexibility through inheritance.
Real-Life Example: A payment application provides a common pay() function. A Credit Card, UPI, and Net Banking each implement pay() differently, so the same function performs different actions depending on the payment method.
#include <iostream>
using namespace std;
// Base class with a virtual function
class Animal
{
public:
virtual void sound()
{
cout << "Animal makes a sound\n";
}
};
// Derived class overriding the base class function
class Dog : public Animal
{
public:
void sound() override
{
cout << "Dog barks\n";
}
};
int main()
{
Animal a;
Dog d;
a.sound();
d.sound();
Animal *ptr = &d;
// Calls derived version due to virtual function
ptr->sound();
return 0;
}
Output
Animal makes a sound Dog barks Dog barks
Explanation: This code demonstrates function overriding in C++, where the Dog class redefines Animalâs sound() function, and the derived version runs via a base class pointer due to runtime polymorphism.
The override Keyword
To avoid mistakes when overriding functions, C++ introduced the override keyword.
- Ensures you're actually overriding a
virtualfunction. - If the signature doesn't match any base class function, the compiler gives an error.
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void sound()
{ // Base class virtual function
cout << "Animal makes a sound\n";
}
};
class Dog : public Animal
{
// Error: Function name does not match base class, compiler will flag this
void Sound() override
{
cout << "Dog barks\n";
}
};
int main()
{
Dog d;
d.Sound(); // This will cause a compile-time error
return 0;
}
Explanation: The override keyword in C++ ensures a derived class function correctly overrides a virtual function from the base class. If the function signature doesn't match, the compiler generates an error, preventing mistakes.
Real-Life Example: Constitution of India
India adopted principles from other countries and redefined them in its own context-just like overriding base behavior with derived custom logic.
Function Overriding Using Base Class Pointer
Runtime polymorphism is commonly achieved by accessing derived class objects through base class pointers or references.
- The function call is resolved according to the actual object type.
- Dynamic binding occurs only for virtual functions.
- Enables flexible and extensible program design.
#include <iostream>
using namespace std;
class Base
{
public:
virtual void display()
{
cout << "Display from Base class" << endl;
}
};
class Derived : public Base
{
public:
void display() override
{
cout << "Display from derived class" << endl;
}
};
int main()
{
Base *basePtr;
Derived derivedObj;
basePtr = &derivedObj;
basePtr->display();
return 0;
}
Output
Display from derived class
Explanation: A base class pointer points to a derived class object. When display() is called, the derived class implementation executes because the function is virtual.
Overriding Without Virtual Function
If the base class function is not declared virtual, the derived class function hides the base class function instead of overriding it.
- Function calls are resolved at compile time.
- Runtime polymorphism is not achieved.
- The base class implementation is called through a base class pointer.
#include <iostream>
using namespace std;
class Animal
{
// Base class with a normal function
public:
void sound()
{
cout << "Animal sound\n";
}
};
class Dog : public Animal
{
// Derived class defines a function with the same name, but it is not overriding
public:
void sound()
{
cout << "Dog barks\n";
}
};
int main()
{
// Base class pointer pointing to a derived object
Animal *a = new Dog();
// Calls base class version because function is not virtual
a->sound();
return 0;
}
Output
Animal sound
Explanation: The Dog class function hides the base class sound() instead of overriding it. Calling sound() through a base class pointer runs the base class version.
Advantages of Function Overriding
Function overriding improves flexibility and reusability by allowing derived classes to redefine inherited behavior.
- Enables runtime polymorphism through dynamic binding.
- Allows derived classes to customize inherited functionality.
- Promotes code reuse using inheritance.
- Encourages programming through base class interfaces.
- Improves extensibility and maintainability of applications.
Limitations of Function Overriding
Although powerful, function overriding introduces some runtime overhead and requires careful implementation.
- Virtual function calls are slightly slower due to dynamic dispatch.
- Requires additional memory for virtual tables (vtables).
- Incorrect function signatures may result in function hiding.
- Deep inheritance hierarchies can increase code complexity.
- Requires careful class design for long-term maintainability.