C++ Function Overriding
Function overriding in C++ is a feature of object-oriented programming that allows a derived class to provide a specific implementation of a function that is already defined in its base class. This mechanism is used to achieve polymorphism, which allows the program to decide at runtime which version of the function to call based on the object type (whether it’s a base class or derived class object).
In function overriding, the signature of the base class function and the overridden function in the derived class must be the same. The overridden function is called when an object of the derived class invokes that function, even when the function is invoked via a pointer or reference of the base class type.
To override a function in C++, the function in the derived class must:
Additionally, the virtual keyword is typically used in the base class function declaration to allow for runtime polymorphism.
class BaseClass {
public:
virtual void functionName() {
// Base class implementation
}
};
class DerivedClass : public BaseClass {
public:
void functionName() override {
// Derived class implementation
}
};
virtual
keyword indicates that the function can be overridden in derived classes.override
keyword (optional, but recommended) is used to indicate that the function is meant to override a base class function.Let’s understand function overriding through an example.
#include <iostream>
using namespace std;
// Base class
class Animal {
public:
virtual void sound() {
cout << "Animal makes a sound!" << endl;
}
};
// Derived class
class Dog : public Animal {
public:
void sound() override {
cout << "Dog barks!" << endl;
}
};
// Another derived class
class Cat : public Animal {
public:
void sound() override {
cout << "Cat meows!" << endl;
}
};
int main() {
Animal* animal1 = new Dog();
Animal* animal2 = new Cat();
animal1->sound(); // Output: Dog barks!
animal2->sound(); // Output: Cat meows!
delete animal1;
delete animal2;
return 0;
}
Explanation:
sound()
function is defined in the base class Animal
and is marked as virtual
to allow overriding.Dog
and Cat
classes override the sound()
function to provide their own implementations.main()
function, we create objects of Dog
and Cat
but use pointers of type Animal*
to call the sound()
function. This demonstrates runtime polymorphism, where the correct version of the function (based on the actual object type) is called at runtime.Virtual Function: In C++, for a function to be overridden in a derived class, it should be declared as virtual
in the base class. This enables dynamic dispatch, where the function call is resolved at runtime based on the object type.
Overridden Function: The function in the derived class must have the same signature as the function in the base class. This includes the function name, return type, and parameters.
Access Modifiers: The access modifiers (like public
, protected
, or private
) should match or be compatible between the base class and the derived class for the overridden function. Typically, functions in the derived class are made public
so that they can be accessed outside the class.
Virtual Table (vtable): When using function overriding, C++ uses a virtual table to ensure that the correct function is called based on the object's actual type at runtime. This mechanism is central to runtime polymorphism.
Override Keyword: The override
keyword is not mandatory, but it is a good practice to use it in the derived class to avoid errors, such as when the function signature in the derived class does not match the base class.
Destructors and Virtual Functions: If a class has a virtual function, its destructor should also be virtual to ensure proper cleanup when an object is deleted through a base class pointer.
In the example below, we will show how to use a virtual destructor to ensure proper cleanup when objects are deleted using base class pointers.
#include <iostream>
using namespace std;
// Base class
class Base {
public:
virtual ~Base() { // Virtual destructor in base class
cout << "Base class destructor called!" << endl;
}
virtual void show() {
cout << "Base class show function" << endl;
}
};
// Derived class
class Derived : public Base {
public:
~Derived() override { // Overriding destructor in derived class
cout << "Derived class destructor called!" << endl;
}
void show() override {
cout << "Derived class show function" << endl;
}
};
int main() {
Base* basePtr = new Derived();
basePtr->show(); // Output: Derived class show function
delete basePtr; // Calls Derived class destructor first, then Base class destructor
return 0;
}
Explanation:
Base
class has a virtual destructor to ensure that the destructor of the derived class (Derived
) is called when deleting a Derived
object using a Base
pointer.delete basePtr;
is called, the destructor of the Derived
class is invoked first, followed by the destructor of the Base
class. This ensures proper resource cleanup in the derived class.You should use function overriding when: