Home Resource Centre Function Overriding In C++ | Working, Call Binding & More (+Codes)

Function Overriding In C++ | Working, Call Binding & More (+Codes)

Function overriding is a fundamental concept in object-oriented programming that empowers developers to create more flexible and specialized classes. It enables a derived class to provide its own implementation of a function inherited from a base class. This mechanism allows for the implementation of polymorphism, a cornerstone of object-oriented programming. In this article, we'll delve into the concept of function overriding in C++ programming, explore its syntax and different scenarios of function overriding, and understand its significance through examples.

What Is Function Overriding In C++?

As mentioned before, function overriding is a feature that allows a derived class to provide a new or custom implementation for a function that has already been defined in its base class. This is important for building hierarchical relationships between classes, where derived classes inherit characteristics and behaviour from their base classes but can also customize or extend those behaviours as needed.

  • When a derived class (child class) overrides a function from its base class (parent class), it provides a new definition for that function with the same function name and signature, i.e., the function prototype.
  • This allows instances of the derived class to respond to method calls with their unique behaviour, even when treated as instances of the base class.
  • Function overriding in C++ is hence vital for achieving polymorphism, where different objects can be treated as instances of a common base class, but their actual behaviour depends on the specific derived class they belong to.

Syntax For Function Overriding In C++

To implement function overriding in C++ language, you need to follow a specific syntax involving both the base class/ parent class and derived classes/ child class. Here's the syntax for function overriding in C++ programs:

class Base {
public:
virtual returnType functionName(parameters) {
// Base class implementation
}
};
class Derived : public Base {
public:
returnType functionName(parameters) override {
// Derived class implementation
}
};

Here,

  • Base is the name given to the parent class, and Derived is the name of the child class, which inherits from Base.
  • Public is the access specifier that defines the visibility mode of the contained data member or member function. A public specifier means that the elements are accessible to other parts of the class.
  • The virtual keyword implies that the function named functionName is a C++ virtual function whose key feature is that it can be overridden.
  • The terms returnType and parameters refer to the data type of the function's return value and the function parameters the respective function takes as input, respectively.
  • The curly brackets following the function declaration contain the function body defining the behaviour of the function. These, as a whole, make up the function definition.
  • The override keyword used in the child class function indicates that the respective function will override the function from the base class.

Now that we know about the components of syntax to implement function overriding in C++ let's look at the basic logic behind it.

  • We begin by declaring a base class, often containing a function that you intend to override in the derived class.
  • The function to be overriden should be marked as virtual to indicate that derived classes can override it.
  • We then declare a derived class that inherits publicly from the base class using the public access specifier.
  • Inside the derived/ child class provide the new implementation for the function you want to override. We must use the override keyword after the function signature to indicate that you intend to override the base class function.

Look at the function overriding in the C++ example below, which illustrates the implementation of this concept.

Code Example:

Output:

Cat meows.
Dog barks.

Explanation:

In the example C++ code, we include the essential header file <iostream> for input/output stream functions.

  1. We then define a base class called Animal, which contains a C++ virtual function called makeSound().
  2. This function uses the cout command to print a string message- 'Animal makes a generic sound.' when called. The virtual keyword in the function definition allows this function to be overridden by derived classes.
  3. Next, we define a derived class Cat that inherits from the base/ parent class Animal. It overrides the makeSound() function with its own implementation that prints the message- 'Cat meows'.
  4. Then, we define a second derived/ child class, Dog, inheriting from the Animal class. It overrides the makeSound() function with its own implementation to print- 'Dog barks'.
  5. In the main() function, which is the entry point for the program's execution, we declare a pointer to the Animal class called animalPtr. It points to the objects of derived classes.
  6. Next, we create two objects, cat and dog, one each for the Cat and Dog child classes, respectively.
  7. After that, we assign the address of object cat to animalPtr using the reference/ address-of operator (&).
  8. We use the animalPtr, which now points to the cat object, to call the makeSound() function using the arrow/ 'this' pointer (->).
  9. This call invokes the overriding makeSound() function from the Cat class, resulting in the output- Cat meows.
  10. Next, we assign the address of dog object to the pointer like before. Then, use the pointer to object with the 'this' pointer to call the makeSound() function.
  11. This function call invokes the overriding implementation of makeSound() from the Dog class, printing the string message 'Dog barks.' on the console.
  12. Finally, the main() function terminates with a return 0 statement indicating successful completion.

The Working Mechanism Of Function Overriding In C++

The example above showcases how function overriding in C++ works in action. In this section, we will explore the working mechanism in greater detail, theoretically.

As we know, function overriding in C++ allows a derived class to provide a new implementation for a function in its base class. This enables polymorphism, i.e., allows objects of different classes to be treated as instances of a common base class while invoking their specific behavior. Let's dive into how function overriding works in C++:

  1. Virtual Functions: At the heart of function overriding is the concept of C++ virtual functions. That is, the functions inside the base class are declared using the virtual keyword. This tells the compiler that derived classes can override the function and that the decision about which function to call should be deferred until runtime. Virtual functions are identified by their unique memory addresses in a table known as the virtual function table or vtable.
  2. Function Signature and Name: To override a function in a derived class, the function must have the same name, parameters, and return type as the base class function. This is crucial for the compiler to recognize the function as an override. If these criteria are not met, the function in the derived class will be considered a new function rather than an override.
  3. The Override Keyword: In C++11 and later versions, the override keyword is used to explicitly indicate that a function in the derived class is intended to override a virtual function from the base class. This helps catch errors at compile time if there's a mismatch between the base and derived class functions.
  4. Dynamic Binding: When you have a base class pointer pointing to an object of a derived class, and you call a virtual function using that pointer, the function that will be executed is determined at runtime. This is known as dynamic binding or late binding or run-time polymorphism. The correct function to call is resolved based on the actual type of the object being pointed to, and this determination is made using the vtable.
  5. vtable Mechanism: The compiler maintains a vtable for each class that contains virtual functions. This table is an array of function pointers. Each entry corresponds to a virtual function in the class, and it points to the appropriate implementation of that function in the derived class. When you call a virtual function through a base class pointer, the vtable is consulted to find the correct function to call based on the actual type of the object.
  6. Base Class Access Specifier: The access specifier used for the virtual function in the base class determines how the function can be accessed in derived classes. If the function is declared as public in the base class, it can be accessed as public or protected in the derived class. If it's declared as protected, it can only be accessed as protected in the derived class.

Real-Life Example Of Function Overriding In C++

Let's consider a real-life example of function overriding in C++ by imagining a scenario involving different shapes. Take shapes, for instance, which encompasses multiple types of shapes. In some sense, Shape is a class with every individual type of shape fulfilling the role of derived/ child class. Let's convert this scenario into C++ code and see how the mechanism transforms.

We'll create a base class called Shape and two derived classes, Circle and Rectangle, both inherited from Shape. Each class will have a function named calculateArea() that calculates the area of the shape, but the formulas for calculating the area will be different for circles and rectangles.

Code Example:

Output:

Circle Area: 78.5397
Rectangle Area: 24

Explanation:

In this C++ example program-

  1. We create a base class, Shape, which contains a public member function calculateArea() defined using the virtual keyword. The default return value for this function is 0.0.
  2. Then, we define a derived class Circle which publicly inherits from the Shape class.
    • It contains a private member variable radius double data type and a public constructor to initialize the data member with the value r.
    • The Circle class then provides an overriding implementation of the calculateArea() function to calculate the area of a circle using the formula π * radius^2.
  3. Next, we declare another child class Rectangle, which also publicly inherits from the Shape class.
    • It contains two private data members, height and width, of double type and a constructor to initialize them.
    • The class also provides an implementation of calculateArea() function with the override keyword to indicate that this must override the virtual function in the base class.
    • This function calculates the area of a rectangle using the arithmetic operator in the formula width * height. 
  4. In the main() function, we create two instances/ objects, circle and rectangle, which belong to the Circle and Rectangle classes, respectively.
  5. The data member of the circle object is initialized with the value 5, and the data members of the rectangle object with the values 4 and 6.
  6. As mentioned in the code comments, we declare base class pointer shapePtr, which will be used to demonstrate polymorphism.
  7. We first assign the address of the object circle to the pointer and call the calculateArea(). As a result, the function from the Cat class is invoked.
  8. Similarly, when the pointer to the object rectangle is used to call calculateArea(), the function from the Rectangle class is invoked.
  9. This way, the overridden functions are called, and the appropriate calculations for circles and rectangles are performed based on the actual object type being pointed to.

This example showcases how function overriding and polymorphism allow objects of different derived classes to be treated through a common base class interface while the specific behavior for each shape is executed based on the overridden functions.

Accessing Overriding Function In C++

In C++, we can access the overriding function by creating the object of the derived class and calling the overriding function either by using the member selector/ dot operator (.) or the 'this' pointer/ arrow pointer(->). We have already seen how to use the 'this' pointer to invoke the overriding function in the example in the previous section. In the sample C++ code below, we will look at the dot operator/ member selector approach to access the overriding function.

Code Example:

Output:

Drawing a circle

Explanation:

  1. In this example, we define a base class Shape and a derived class Circle which publically inherits from the base class. 
  2. The Circle class overrides the draw() function initially defined in the base class.
  3. In the main() function, we create an object circle of class Circle and then call the draw() function using the member selector (.)
  4. This invokes the draw() function implementation from the Circle class since the object used belongs to that class.
  5. Note that when using this approach, we do not need to create a pointer to the base class as in the case of the 'this' pointer.

Accessing Overridden Function In C++

In C++, you can access an overridden function in a derived class by using either of the following two methods:

  1. Using pointers
  2. Using scope resolution operator

Pointer Approach To Access Overriden Function In C++

As you must know, a pointer is a data type that stores the address of other data types. Pointers can be used for base class objects as well as objects of derived classes. Here are a few things we must note about pointers when it comes to classes:

  • A pointer of the base class type can point to different derived class objects and can still use all the privileges of the base class
  • A pointer to the object of the derived class and a pointer to the object of the base class are type-compatible.
  • A pointer of one class type can point to another class, but the relationship between them should be base class and derived class.

Hence, we can use pointers to access an overridden function. the example given below showcases how this can be done.

Code Example:

Output:

Drawing a shape(base class)
Drawing a circle(derived class)
Drawing a shape(base class)

Explanation:

  1. In this example, there is a parent/ base class Shape with a draw() function. From this, we derive class Circle, which overrides the draw() function.
  2. Then, in the main() function, we created a pointer to the base class s (i.e., Shape* s). Here, we use the new() operator to dynamically allocate memory to the object of the Shape class.
  3. Next, using the pointer s with the arrow operator, we call the overridden function from the base class.
  4. Since the pointer is a pointer to an object of the Shape class, the overridden function from the base class will be invoked.
  5. Then, we create an object c of the Circle class and use it with the member selector to call the draw() function. This will invoke the overriding function from the derived class since the object used belongs to that class.
  6. After that, we assign the address of object c to the pointer s, i.e., s = &c. This means that s is now pointing to object c.
  7. We then call the draw() function again, but this time, we use pointer s with the 'this' pointer. 
  8. Note that the base class properties and behaviors have higher priority than derived classes when you call a function through base class type pointers until they are virtual.
  9. The draw() function was not marked as virtual, and the pointer s originally belonged to the base class pointing to derived class objects; it doesn’t have full access to derived class properties and behaviors.
  10. This is why the last function call will invoke the overridden function from the base class, as shown in the output console.
  11. When you create a pointer to a derived class, it can access its class properties and base class properties.

Scope Resolution Operator Approach To Access Overriden Function In C++

When using the scope resolution operator to access the members of a class, we must use the object name, the class name, the scope resolution operator and then the name of the member variable/ function we want to access. This gives us the ability to access a member function from either the derived class or base class using objects. Within the scope resolution operator approach, there are two ways to access the overridden function. Both of these are explained ahead.

Accessing Overridden Function Using The Derived Class Object

The scope resolution operator (::) is used to access the base class member function (overridden function) with the help of a derived class object. This is typically used when the derived class overrides the base class member.

Syntax:

derived_object.base_class::function_name();

Here,

  • derived _object: It denotes the object of the derived class which overrides the base class
  • base_class: It is the name of the base class
  • function_name: it denotes the name of the overridden base class function

Let's look at a sample C++ code that shows how we can use the scope resolution operator with the derived object to access the overridden function.

Code Example:

Output:

Drawing a circle(derived class)
Drawing a shape(base class)

Explanation

  1. In this example, we define a base class called Shape with a method draw(), which prints the string- 'Drawing a shape(base class)' using the cout command.
  2. Next, we define a derived class Circle, which inherits from the Shape class and provides its own implementation of the draw() function.
  3. Note that both the functions are defined as void, so we don't use the virtual or override keywords.
  4. In the main() function, we create an instance/ object c of Circle class and use it to call the draw() function twice.
    • c.draw() calls and executes the overridden draw() method in Circle, this printing 'Drawing a circle(derived class)'.
    • c.Shape::draw() uses the circle object and the scope operator to explicitly invoke the base class Shape's draw() method and print "Drawing a shape(base class)".
  5. The program concludes with a return of 0.

Accessing Overridden Function Inside The Derived Class

In C++, when you override a function in a derived class, you're essentially replacing the implementation of that function from the base class with a new implementation in the derived class. However, sometimes, you might want to access the overridden function from within the derived class. This can be done using the scope resolution operator (::) along with the base class name.

Syntax:

base_class::function_name()

Here,

  • base_class: It denotes the name of the base class where the overridden function is defined
  • function_name: It denotes the name of the overridden function

Code Example:

Output:

Drawing a shape(base class)
Drawing a circle(derived class)

Explanation:

  1. We define a Shape class representing a basic geometric shape.
  2. Inside the Shape class, we have a draw() function, which prints a message indicating that a shape is being drawn. This function serves as the base implementation.
  3. We define a Circle class that inherits from the Shape class, signified by the public keyword.
  4. Inside the Circle class, we override the draw() function. In the overridden draw() function, we first call Shape::draw() using the scope resolution operator (::) to access the draw() function of the base class Shape. This allows us to execute the base class's draw() function before adding additional functionality.
  5. After calling Shape::draw(), we print a message indicating that a circle is being drawn.
  6. In the main() function, we create an instance of the Circle class named c.
  7. We call the draw() function on the c object, which triggers the overridden draw() function in the Circle class.

Function Call Binding With Class Objects | Function Overriding In C++

In C++, when you have a class object and you invoke a member function using the object, the function call is bound to that object. This is known as function call binding or dynamic dispatch. The example of member function/ method overriding in C++ is given below. 

Code Example:

Output:

Drawing a shape(base class)
Drawing a circle(derived class)

Explanation:

  1. In this example, we have two classes, Shape and Circle, where Circle is inherited from Shape, and both classes implement the draw() function.
  2. Inside the main() function, we create objects of both classes, Shape and Circle, called s and c, respectively. We then invoke the draw() function using these objects separately, using the member selector approach.
  3. Here, the function call is dynamically bound based on the actual type of the object.
  4. The s.draw() calls a Shape::draw() because ‘s’ is a Shape class object. Similarly, c.draw() calls Circle::draw().
  5. The output is printed to the console with the cout command implementation in both functions.

Function Call Binding With Base Class Pointers | Function Overriding In C++

When you use a base class pointer to invoke a member function, the function call is dynamically bound based on the actual type of the object the pointer is pointing to. And not the type of the object itself, as in the section above. This is also an important component of the polymorphism concept. The member function overriding in C++ example below provides an implementation of this type of function call binding. 

Code Example:

Output:

Drawing a circle(derived class)

Explanation:

  1. In this example, we have defined two classes: Shape and Circle.
  2. The derived class Circle inherits from the base class Shape and overrides the draw() function.
  3. In the main() function, we create the base class pointer s, as well as an object of Circle class, c.
  4. Next, we assign the address of a derived class object to a base class pointer using an upcast (i.e., s=&c).
  5. Next, we invoke the draw() function using the 'this' pointer, where the function call is dynamically bound.
  6. The actual type of the object being pointed to is determined at runtime, and the appropriate version of the draw() function is called.
  7. In this case, Circle::draw() is called because 's' is pointing to an object of type Circle.

Advantages Of Function Overriding In C++

Function overriding in C++ and other object-oriented languages offers several advantages that contribute to the flexibility and extensibility of software development. Here are some key advantages of function overriding in C++:

  1. Polymorphism: Function overriding enables polymorphism, which allows different objects to respond differently to the same method call. This is essential for creating generic code that can work with multiple types of objects without needing to know their specific implementations.
  2. Dynamic Method Dispatch: With function overriding in C++ programs, the actual method to be called is determined at runtime based on the actual type of the object, not just the reference type. This dynamic method dispatch allows for flexible and late-bound execution of methods.
  3. Specialization: Subclasses can provide specialized implementations of methods inherited from their superclass. This allows you to fine-tune the behavior for specific types of objects while maintaining the consistency of code.
  4. Code Reusability: By defining methods in a superclass and allowing subclasses to override them, you can reuse common code snippets across different classes. This helps reduce redundancy and maintain a modular codebase, hence making the code clean.
  5. Framework Design: Function overriding in C++ is fundamental to building software frameworks and libraries. It provides a way for developers to extend and customize the behavior of framework components without altering the core driver code.
  6. Ease of Maintenance: Overriding promotes separation of concerns and modular design. Changes made to overridden methods in subclasses do not affect the superclass or other subclasses, making it easier to maintain and evolve the codebase over time.
  7. Abstraction: Function overriding in C++ allows you to define abstract methods in a base class (using the virtual keyword and without providing an implementation) and enforce that derived classes provide their own implementation. This enforces a contract for subclasses to adhere to.
  8. Runtime Polymorphism: The ability to change the behavior of a program during runtime based on the type of objects being used enhances the adaptability and robustness of software systems.
  9. Encapsulation: Overriding enables you to encapsulate the implementation details of a class while still allowing subclasses to customize specific behaviors. This enhances information hiding and protects internal implementation details.
  10. Compatibility: By adhering to a common interface in the base class, you ensure that all derived classes maintain a consistent API. This makes it easier to swap objects of different classes without disrupting the functionality of the program.

Variations In Function Overriding In C++

There are three primary variations of function overriding in C++. This includes basic function overriding, virtual function overriding, and non-virtual function overriding. We have discussed all these variations below in detail, with the help of examples.

Basic Function Overriding In C++

It occurs when the derived class redefines the function of the base class with the same name, return type, no of parameters, and type of parameters. We have already discussed this in detail in the sections above. We know how to override and invoke a base class function by using base class pointers, member selectors, and the scope resolution operator.

Let's look at another example. However, here we will invoke the overriding function by creating a pointer to the derived class (as against the base class).

Code Example:

Output:

Drawing a circle(derived class)

Explanation:

  1. In this example, we have defined two classes, Shape and Circle. The Circle class inherits from the Shape class and overrides the draw() function.
  2. In the main() function, we declare the pointer to the derived class Circle and use this pointer to call the draw() function.
  3. As a result, the derived class will implement its draw(). That is, if we invoke the draw() function using the derived class pointer, it will bind to Circle::draw().

Virtual Function Overriding In C++

Virtual function overriding expands upon basic function overriding by introducing the concept of dynamic binding and polymorphism. Here,

  • The base class function has to be marked as virtual to allow for virtual function overriding.
  • This allows the appropriate derived class implementation to be executed based on the actual object type, even when the function is called through a base class reference or pointer.

Let's look at an example of this for a better understanding.

Code Example:

Output:

Drawing a shape(base class)
Drawing a circle(derived class)

Explanation:

In the C++ program example,

  1. We first define a base class Shape with the draw() function. Then, define a derived class Circle, which inherits from Shape and overrides the draw() function.
  2. In the main() function, we define the pointer to base class, s and invoke the draw() function using this pointer. This will call the base class method.
  3. Next, we create a derived class object c and assign its address to ‘s’. That is, it will point to the derived class object even though it is a base class pointer
  4. Note that both base class and derived class types are type-compatible.
  5. Now, calling the draw() function will call the derived class function because the actual type of object s is pointed is Circle.
  6. In case the derived class won’t override the virtual base class function, then s->draw() will call the base class virtual function.

Also learn about- Pure Virtual Function In C++ & Abstract Classes ( With Examples)

Non-Virtual Function Overriding In C++

Say a function is defined in a base class and redefined in a derived class with the same name and signature. Then, if you have a base class pointer pointing to a derived class object and call the execution of a function through that pointer, it will invoke the base class function, not the child function. This type of variation is less common because it does not provide flexibility and dynamic polymorphism.

Code Example:

Output:

Drawing a shape(base class)

Explanation:

  1. In this example, we have defined a base class Shape with the draw() function that prints 'Drawing a shape(base class)' using the cout command.
  2. Then we have a derived class Circle, which inherits from the Shape class and overrides the draw() function and prints 'Drawing a shape(derived class).
  3. Then, in the main() function, we create a base class pointer s and a derived class object c.
  4. When we assign the address of c to s, so the pointer s will point to the derived class object.
  5. Since all the functions are non-virtual, calling to draw() through the pointer will invoke the base class function. This is shown in the output.

Note- Even though C++ allows a base pointer to point to any object derived from that base, the pointer can’t be directly used to access all the properties and behaviors of the derived class.

We may have to use another pointer declared as a pointer to the derived type to access all derived class members.

Function Overloading In C++

Function overloading in C++ allows you to define multiple functions with the same name but different input parameters, return type, or no of parameters such that the compiler can differentiate all the similar functions by some means. It is also known as compile-time or static polymorphism. It provides a way to create functions that perform similar operations. It differs from overriding since we are not using the concept of classes to encapsulate functions or data members.

Code Example:

Output:

Area of the square: 25
Area of the rectangle: 24

Explanation:

In this example,

  1. We have two overloaded functions named calculateArea(). Each function execution takes different parameters to calculate the area of a square and rectangle
  2. The first calculateArea() function calculates the area of a square given the side length.
  3. The second calculateArea() function calculates the area of a rectangle given the length and width.
  4. In the main function, we call both functions, which are called with different arguments to calculate the respective areas.
  5. The compiler determines which function to invoke when based on the arguments, and results are printed to the console using cout.

Also Read: Function Overloading In C++ With Code Examples & Explanation

Function Overloading Vs Function Overriding In C++

Some of the key differences between function overloading and function overriding are as follows:

Function Overriding

Function Overloading

When a derived class specifies a function with the same name and signature as a function in its base class, then it is known as function overriding.

Function overloading allows multiple functions with the same name but different parameter lists, return types, or no of parameters.

The compiler can’t distinguish the functions.

The compiler can distinguish between the overloaded functions.

Overridden function declaration should have the same signature or prototype.

The overloaded function body should have different parameters or return types.

Overriding requires a base class and a derived class with an inheritance relationship.

Overloaded functions may or may not have a relationship between them in terms of inheritance.

It is run-time polymorphism or late binding.

It is compile-time polymorphism or early binding.

Virtual keyword is required.

No special keyword is required.

Time complexity is high.

Time complexity is low.

Dynamic in nature.

Static in nature.

It is used when we want to achieve the task based on preferences.

It is used when we want to achieve the same task using different ways.

Conclusion

In conclusion, function overriding stands as a cornerstone of object-oriented programming within the C++ language. Through the intricate interplay of inheritance, virtual functions, and dynamic binding, function overriding enables the realization of polymorphism- a defining characteristic of OOP. The concept of function overriding in C++ empowers developers to build versatile and maintainable code by fostering code reusability, flexibility, and hierarchy.

By adhering to the principles of maintaining consistent function signatures, utilizing the virtual keyword judiciously, and adhering to appropriate access controls, developers can create class hierarchies that embody specialization and elegant design. This not only enhances the efficiency of the development process but also facilitates the treatment of diverse objects under a unified interface, promoting a high degree of abstraction and enhancing the overall quality of the codebase. With function overriding, C++ showcases its prowess as an object-oriented programming language that encourages elegant solutions and promotes efficient code design.

Frequently Asked Questions

Q. What is overriding in C++? Explain function overriding in C++ with a simple code example.

As the name suggests, overriding refers to the act of cancelling out the authority of something. In C++ programming, function overriding refers to the ability of a derived class to provide its implementation of a function that is already defined in its base class. It allows the derived class to customize the behavior of the inherited function by overriding them while preserving the same name and signature.

Code Example:

Output:

Animal makes a sound.
Dog barks.

Code Explanation:

In this example-

  1. We define a base class called Animal containing a virtual function makeSound(). The virtual keyword indicates that this function can be overridden in derived classes. 
  2. We then define a derived class called Dog, which inherits from the Animal class. The makeSound() function in the Dog class overrides the base class implementation.
  3. In the main() function, we create two pointers: animal of type Animal* and dog of type Dog*. These pointers are used to dynamically allocate memory for an instance of Animal and Dog, respectively, using the new keyword. 
  4. The animal->makeSound(); line calls the makeSound() function on the base class object pointed to by the animal pointer. Since the makeSound() function is declared as virtual in the base class, the actual function that gets executed depends on the object's runtime type. 
  5. The dog->makeSound(); line calls the makeSound() function on the derived class object pointed to by the dog pointer. Since the makeSound() function is overridden in the Dog class
  6. After using the dynamically allocated objects, the delete keyword is used to free the allocated memory for both the animal and the dog. This is essential to prevent memory leaks.
  7. The return 0; line ends the main() function and indicates successful execution to the operating system.

Q. What are the limitations of virtual functions?

Some of the limitations of the C++ virtual functions are:

  • Slower: Because of the virtual mechanism, the call to these functions takes a little bit longer. This makes it harder for the compiler to optimize because it does not know precisely which function will be called at compile time.
  • Difficult to Debug: Virtual functions can make it slightly more challenging to determine where a function is being called from in complex systems.
  • Limited to Class Hierarchies: Virtual functions are primarily designed to work within class hierarchies, where derived classes override base class functions. They are not suitable for standalone functions or non-inheritance scenarios
  • Cannot be Static or Friend Functions: Virtual functions cannot be declared as static or friend functions. Virtual functions require dynamic dispatch, which is not compatible with static or non-member functions.

Q. Which functions cannot be overridden?

Given below is a list of the functions that cannot be overridden in C++:

  • Constructors: These are special member functions used to initialize objects. They can't be declared as virtual, which makes it impossible to override them. It's important to keep in mind that constructors can be called via inheritance when we create an object of the derived class.
  • Static functions: Instead of being associated with class instances, static functions are part of the class itself. They lack this pointer and are not connected to any specific object. Static functions cannot be overridden since they are resolved based on the static type at build time.
  • Non-member functions and friend functions: Neither global nor friend functions, which are not members of a class, can be overridden.
  • Final functions: The functions that are declared with the final keyword are intended not to be overridden, so they can’t be overridden in the derived class.

Q. What is the difference between function overriding vs function hiding?

Here are the differences between function hiding and function overriding in C++:

Aspect Function Overriding Function Hiding (Static Method Overriding)
Method Signature Method signature must match in both superclass and subclass. Method signature can differ in both superclass and subclass.
Polymorphism Follows polymorphic behavior. The actual method called depends on the actual object's type. Does not follow polymorphic behavior. The actual method called depends on the reference type.
Use of Keywords Requires the use of virtual keyword in the base class method and override keyword in the derived class method. No specific keywords are used for method hiding. It's based on the method name and signature alone.
Static vs. Instance Applies to instance methods (non-static). This applies to static methods.
Memory and Performance Slightly higher memory overhead due to virtual function table (vtable) in some languages. Slight runtime performance impact due to dynamic dispatch. No virtual function table. A static method is called directly, potentially slightly better performance.
Example (C++) cpp class Base{
public:
virtual void foo(){/* ... */ }};
class Derived:public Base{
public:
void foo() override{/* ... */ }};
cpp class Parent{
public:
static void foo(){/* ... */ }};
class Child:public Parent{
public:
static void foo() { /* ... */ } };

Q. What is overriding in C++ and its types?

Function overriding is a feature in object-oriented programming languages like C++ that allows a derived class to provide a different implementation of a method that is already defined in its base class. The overridden method in the child class (derived class) has the same name, return type, and parameters as the method in the base class. There are two main types of function overriding:

  • Early or Static Binding Overriding: This type of overriding takes place during compile-time. That is, the function that will be executed in a static override is chosen depending on the object's static type or the type declared at compile time.
  • Late or dynamic binding Overriding: This kind of overriding takes place at runtime. The function to be executed is determined based on the dynamic type of the object, i.e., the type of the object created at runtime.

Q.Why is function overriding called runtime polymorphism?

Function overriding is also referred to as runtime polymorphism because it is the ability of an object-oriented programming language to determine, at runtime, which implementation of a method or original function to invoke. This decision is based on the actual type of the object that the method is being called on.

This is in contrast to compile-time polymorphism, also known as function overloading, where the compiler makes the decision about which function to call at compile-time based on the number and types of arguments.

  • In the context of object-oriented programming, function overriding occurs when a subclass (child class) provides a specific implementation for a method that is already defined in its superclass (parent class).
  • The signature of the method in the subclass (i.e., the method name, return type, and parameters) must match that of the method in the superclass.
  • However, the actual behavior or implementation can differ between the superclass and the subclass.
  • The term polymorphism refers to the ability of different classes to be treated as instances of a common superclass and for the appropriate method to be selected dynamically at runtime based on the actual type of the parent object.
  • So, when we call a method on an object, the runtime environment (e.g., the virtual function table in languages like C++ or the method dispatch mechanism in Java) determines which implementation of the method to invoke based on the actual class of the object, not just the reference type.
  • This dynamic method dispatch during runtime gives rise to the term runtime polymorphism. It allows for flexible and extensible pieces of code since you can create new subclasses that override methods and add specialized behavior without changing the overall structure of the program.

All in all, function overriding is referred to as runtime polymorphism because the decision about which method implementation to execute is determined dynamically at runtime based on the actual type of the object. This was, function overriding in C++ allows for more flexible and dynamic behavior in object-oriented programs.

Knowledge is wealth; check out the following C++ topics to learn more:

    1. Destructor In C++ | Understanding The Key To Cleanups (+ Examples)
    2. C++ Templates | Class, Function, & Specialization (With Examples)
    3. Inline Function In C++ | Declaration, Working, Examples & More
    4. Constant In C++ | Literals, Objects, Functions & More (+Examples)
    5. C++ Type Conversion & Type Casting Demystified (With Examples)
Shivani Goyal
Manager, Content

I am an economics graduate using my qualifications and life skills to observe & absorb what life has to offer. A strong believer in 'Don't die before you are dead' philosophy, at Unstop I am producing content that resonates and enables you to be #Unstoppable. When I don't have to be presentable for the job, I'd be elbow deep in paint/ pencil residue, immersed in a good read or socializing in the flesh.

TAGS
Computer Science Engineering
Updated On: 8 May'24, 03:09 PM IST