
- C++ Home
- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Hello World
- C++ Omitting Namespace
- C++ Tokens
- C++ Constants/Literals
- C++ Keywords
- C++ Identifiers
- C++ Data Types
- C++ Numeric Data Types
- C++ Character Data Type
- C++ Boolean Data Type
- C++ Variable Types
- C++ Variable Scope
- C++ Multiple Variables
- C++ Basic Input/Output
- C++ Modifier Types
- C++ Storage Classes
- C++ Numbers
- C++ Enumeration
- C++ Enum Class
- C++ References
- C++ Date & Time
- C++ Operators
- C++ Arithmetic Operators
- C++ Relational Operators
- C++ Logical Operators
- C++ Bitwise Operators
- C++ Assignment Operators
- C++ sizeof Operator
- C++ Conditional Operator
- C++ Comma Operator
- C++ Member Operators
- C++ Casting Operators
- C++ Pointer Operators
- C++ Operators Precedence
- C++ Unary Operators
- C++ Control Statements
- C++ Decision Making
- C++ if Statement
- C++ if else Statement
- C++ Nested if Statements
- C++ switch Statement
- C++ Nested switch Statements
- C++ Loop Types
- C++ while Loop
- C++ for Loop
- C++ do while Loop
- C++ Foreach Loop
- C++ Nested Loops
- C++ break Statement
- C++ continue Statement
- C++ goto Statement
- C++ Strings
- C++ Strings
- C++ Loop Through a String
- C++ String Length
- C++ String Concatenation
- C++ String Comparison
- C++ Functions
- C++ Functions
- C++ Multiple Function Parameters
- C++ Recursive Function
- C++ Return Values
- C++ Function Overloading
- C++ Function Overriding
- C++ Default Arguments
- C++ Arrays
- C++ Arrays
- C++ Multidimensional Arrays
- C++ Pointer to an Array
- C++ Passing Arrays to Functions
- C++ Return Array from Functions
- C++ Structure & Union
- C++ Structures
- C++ Unions
- C++ Pointers
- C++ Pointers
- C++ Dereferencing
- C++ Modify Pointers
- C++ Class and Objects
- C++ Object Oriented
- C++ Classes & Objects
- C++ Class Member Functions
- C++ Class Access Modifiers
- C++ Static Class Members
- C++ Static Data Members
- C++ Static Member Function
- C++ Inline Functions
- C++ this Pointer
- C++ Friend Functions
- C++ Pointer to Classes
- C++ Constructors
- C++ Constructor & Destructor
- C++ Default Constructors
- C++ Parameterized Constructors
- C++ Copy Constructor
- C++ Constructor Overloading
- C++ Constructor with Default Arguments
- C++ Delegating Constructors
- C++ Constructor Initialization List
- C++ Dynamic Initialization Using Constructors
- C++ Object-oriented
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Virtual Function
- C++ Pure Virtual Functions & Abstract Classes
- C++ File Handling
- C++ Files and Streams
- C++ Reading From File
- C++ Advanced
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Socket Programming
- C++ Concurrency
- C++ Advanced Concepts
- C++ Lambda Expression
- C++ unordered_multiset
Function Overriding in C++
A function is a collection of code blocks with instructions inside, which is used for specific tasks. It is meant to be reused as per requirement, making the division of complex problems into smaller and manageable pieces.
What is Function Overriding in C++?
Function overriding is a concept of object-oriented programming which allows a derived class to redefine a function that is already defined in the base class.
Here the method's name and parameters remain the same, but the derived class changes its behavior to suit their specific needs.
Example
Lets consider these 2 functions; one is base class (a) and another is derived class (b), and the function (c) is the main(), where we are implementing overriding −
Function (a)
class base { public: void notice( ) cout << "This is my Base Class" ; }
Function (b)
class derived: public base { public: void notice( ) cout << "This is my Derived Class"; }
Function (c)
void main ( ) { // creating an object for base class and calling it base b; b.notice( ); // creating an object for derived class and calling it derived d ; d.notice( ); }
Overriding Explanation
- Here, we have created an object of base and derived class of 'function (a) and function(b)' respectively and called them inside function (c) as shown, "b.notice() and d.notice()" respectively.
- In this case, for derived class d.notice() will be executed first because it represents the most up-to-date or updated version of the function
- However, if we create an object of the base class as shown in function(c) "b.msg()" and call it, it will use the original version from the base class.
In short, function overriding occurs when the functionality of the base class is redefined in the derived class. When an object of the derived class is created, it will call the updated function from the derived class, meaning that the base class function (a) is overridden by the derived class function (b).
Function overriding is an essential concept in object-oriented programming, enabling polymorphism and dynamic binding.
Example of Function Overriding
Below is a simple example illustrating how overriding works
#include <iostream> using namespace std; // Base class class Shape { public: // Virtual method to be overridden virtual void draw() const { cout << "Drawing a shape" << endl; } }; // Derived class Circle class Circle : public Shape { public: // Overriding the base class method void draw() const override { cout << "Drawing a circle" << endl; } }; // Derived class Square class Square : public Shape { public: // Overriding the base class method void draw() const override { cout << "Drawing a square" << endl; } }; // Main function int main() { Shape* shapePtr; Circle circle; Square square; // Point to Circle and call draw() shapePtr = &circle; shapePtr->draw(); // Outputs: Drawing a circle // Point to Square and call draw() shapePtr = □ shapePtr->draw(); // Outputs: Drawing a square return 0; }
Output
Drawing a circle Drawing a square
Function Overriding Vs. Function Overloading
Although Function Overriding and Function Overloading are essential key-concepts of Object-oriented programming in C++, they both do serve different purposes.
Function overriding allows derived class to get new implementation of method to its previously defined base class, as having different scopes(base class and derived class) where it resolved at runtime polymorphism(dynamic binding), it only take place in presence of inheritance and can overridden just once, where execution speed relatively slower.
Whereas, function overloading enables you to create multiple functions with the same name but different parameter lists within the same scope. It is resolved at compile time polymorphism (static binding), where presence of inheritance is not important, These functions can be overloaded multiple times and execution speed tends to be faster comparatively.
Advanced Overriding Concepts
Heres a list of additional sub topics covering advanced overriding concepts −
1. Virtual Destructor
A virtual destructor makes sure that the destructor of the derived class will be executed when an object is removed through a base class pointer. Function overriding with virtual destructors avoids resource leaks and unpredictable behavior by ensuring proper deletion of objects through base class pointers.
Example
#include <iostream> using namespace std; class BaseClass { public: virtual ~BaseClass() { // Virtual destructor cout << "BaseClass destructor" << endl; } }; class DerivedClass : public BaseClass { public: ~DerivedClass() override { // Overriding destructor cout << "DerivedClass destructor" << endl; } }; int main() { BaseClass* a = new DerivedClass(); // Calls DerivedClass's destructor followed // by BaseClass's destructor delete a; return 0; }
Output
DerivedClass destructor BaseClass destructor
2. Covariant Return Value Types
Covariant return types allow derived classes to override a method and return a more specific type than the base class method. This means that a derived class can return a pointer or reference to a more derived type, rather than just the base type. Function overriding improves flexibility and precision in object-oriented programming.
Note
In the derived class, the return type must be a pointer or reference to a type that is derived from the return type of the base class.
Example
#include <iostream> using namespace std; class Vehicle { public: // Final method virtual void honk() final { cout << "Vehicle honk: Beep beep!" << endl; } }; class SportsCar : public Vehicle { // Cannot override honk() here }; int main() { Vehicle* v = new SportsCar(); v->honk(); // Calls Vehicle's honk() method delete v; return 0; }
Output
Vehicle honk: Beep beep!
3. Overriding and final Keyword alternate word
The `final` keyword stops any further subclassing of a class or overriding of a method.
Function overriding with the `final` keyword is important because it guarantees that a class or method cannot be further changed or extended.
Example
#include <iostream> using namespace std; class Subject { public: // Final method virtual void examType() final { cout << "This subject has a written exam." << endl; } }; class Math : public Subject { // Cannot override examType() here }; int main() { Subject* s = new Math(); s->examType(); // Calls Subject's examType() method delete s; return 0; }
Output
This subject has a written exam.
4. Virtual Inheritance
Virtual inheritance in C++ tackles problems which arise with multiple inheritance, particularly the diamond problem. It ensures that when a class inherits from several base classes which have a common ancestor, only a single instance of that common base class is created.
Virtual inheritance makes sure that only one copy of a base class is used when multiple derived classes share that base class in a hierarchy.
Example
#include <iostream> using namespace std; class Base { public: void present() { cout << "Display from Base class" << endl; } }; class A : virtual public Base { }; class B : virtual public Base { }; class Final : public A, public B { public: void get() { cout << "Display from Final class" << endl; } }; int main() { Final obj; // Displays: Display from Base class obj.present(); // Displays: Display from Final class obj.get(); return 0; }
Output
Display from Base class Display from Final class
Advantages of Function Overriding
1. Polymorphism
Overriding enables polymorphism by letting objects of different derived classes be treated as instances of a base class. This allows dynamic method binding at runtime, where the correct method implementation is chosen based on the object type, thus enhancing flexibility and adaptability, making it a fundamental component of polymorphism.
2. Code Reusability
Developers can utilize existing code by inheriting methods from a base class and customizing them in derived classes. This approach fosters a more streamlined and organized code structure.
3. Maintainability
Overriding promotes a modular design by encapsulating various functionalities within distinct classes. This approach simplifies understanding, maintaining, updating and extending the code.
4. Design Patterns
Overriding plays a key role in the Template Method pattern by defining the overall structure of an algorithm in a base class, while permitting subclasses to override specific steps.
The Strategy pattern leverages overriding to encapsulate various algorithms and enable their interchange at runtime.
5. Memory Management
When using inheritance and dynamic memory allocation, virtual destructors are vital for proper memory management. Overriding the destructor in derived classes ensures that resources allocated by the base and derived classes are correctly deallocated, which prevents memory leaks and ensures clean resource release.