Table of Contents:
- What is a Virtual Function in C++?
- Rules for Virtual Functions in C++
- Reasons for Using the Virtual Functions in C++
- Working of Virtual Functions in C++
- Limitations of Virtual Functions in C++
- Compile time VS runtime behavior of Virtual Functions in C++
- Conclusion
In object-oriented programming, one of the principles of polymorphism is that objects belonging to different classes may be treated as objects of a common base class. In C++, polymorphism is mainly achieved through the use of virtual functions, just as it allows dynamic method resolution to occur with runtime binding.
In this article, we will discuss the need for virtual functions c++, their uses and rules, working and limitations, and a comparison of their behavior.
What is a Virtual Function in C++?
A virtual function is a member function in C++ that is declared in the base class with the keyword virtual and is meant to be overridden in a derived class. It permits late binding that the function call is resolved at runtime based on the actual type of the object, and not at compile time.
Example:
Output:
The code shows virtual functions in C++, where a base class function is marked as virtual to enable binding. When a base class pointer points to a derived class object, the overridden function in the derived class is invoked at runtime instead of the base class version.
Rules for Virtual Functions in C++
- It must be declared using the virtual keyword in the base class.
- The virtual function can be overridden by a derived class using the same signature only.
- Virtual functions are resolved at runtime using the vtable and vptr mechanism.
- Virtual functions belong to classes, so they cannot be static.
- Constructors cannot be virtual, but destructors should be virtual to ensure proper cleanup.
- If a class has at least one virtual function, the compiler creates a vtable.
- Declaring a virtual function as equal to 0 makes it pure virtual, and requires derived classes to implement it.
Get 100% Hike!
Master Most in Demand Skills Now!
Reasons for Using the Virtual Functions in C++
1. Enable Runtime Polymorphism: It allows the function calls to be resolved at the time of runtime which is based on the actual object.
Example:
Output:
The code shows runtime polymorphism in virtual functions in C++, where a base class function is marked as virtual to enablebinding.
2. Achieve Binding: It makes sure that the correct overridden function is used when using the base class pointers or the references.
Example:
Output:
The virtual function show()in this code ensures dynamic binding in the base class, allowing the correct function to be called.
3. Support Code Reusability: It helps us in writing extendable and maintainable object-oriented programs.
Example:
Output:
This code shows code reusability by using a base class (Animal) with a virtual function (makeSound).
4. Avoid Manual Type Checking: It eliminates the need for the statements that are used to determine object types.
Example:
Output:
The virtual function draw() ensures the correct function is called at runtime, avoiding the need for manual type checking, and the renderShape() function works with any derived class without identifying the object type.
5. Ensure Proper Destructor Call: It helps to prevent memory leaks by ensuring that the derived class destructor is correctly called.
Example:
Output:
The virtual function ensures that when deleting a base class pointer, the derived class destructor executes first. Also, without a virtual destructor, only the base class destructor would run, causing incomplete cleanup.
6. Facilitate Interface Design: It allows the defining base class interface so that the derived class can be implemented without making changes in the existing codes.
Example:
Output:
This code shows how the interface design is facilitated by the virtual functions.
Working of Virtual Functions in C++
The virtual functions in C++ enable binding using a method called the Virtual Table (vtable) and Virtual Pointer (vptr).
1. Virtual Table (vtable):
- Each class with virtual functions has a vtable, which is a table storing function pointers to the virtual functions of that class.
- If a derived class overrides a virtual function, its vtable contains a pointer to the overridden function.
2. Virtual Pointer (vptr):
- Every object of a class with virtual functions contains a hidden pointer (vptr) pointing to the class’s vtable.
- When a virtual function is called through a base class pointer, the vptr is used to fetch the correct function from the vtable at runtime.
Example:
Output:
The above code shows how the vtable and vptr are used for binding in C++.
Limitations of Virtual Functions in C++
- The extra indirection via vtable makes the virtual function calls slower.
- The use of virtual functions increases memory usage, as it requires vtable and vptr.
- The compiler cannot inline virtual functions, thus reducing optimization.
- Managing vtable and dynamic dispatch increases program complexity.
- The manipulation in vtable can lead to security issues.
- Also managing multiple vtables can be complex and may cause errors.
Compile time vs Runtime Behavior of Virtual Functions in C++
1. Compile-Time Behavior:
- The constructor creates a vtable for classes with virtual methods.
- Every class with virtual methods has its own vptr, set up in its constructor.
- Non-virtual methods are statically bound at compile time.
- The compiler checks function declaration, overriding rules, and access control.
2. Runtime Behavior:
- Dynamically-vtable-resolved virtual function calls at runtime.
- The vptr checks which function was implemented.
- Calls are executed depending on the actual type of the referenced object at runtime.
- Virtual function calls are lengths just a bit slower than non-virtual ones as they have to deal with vtable.
Example:
Output:
The code shows early (compile-time) and late (runtime) binding in C++ using virtual functions. The show() function is virtual, so it is resolved at runtime (calls Derived::show()), while display() is non-virtual, so it follows compile-time binding (calls Base::display()).
Feature | Compile-time Behavior | Runtime Behavior |
Function Binding | Static(Early) Binding | Dynamic(Late) Binding |
Function Resolution | Resolved by compiler | Resolved via vtable at runtime |
Speed | Faster | Slightly slower |
Function call technique | Direct function call | Uses vtable lookup |
Works with | Normal functions | Virtual functions |
Conclusion
Virtual functions enable runtime polymorphism in C++, realized by the mechanism of vtable and vptr in dynamic function resolution. The advantages of these are the reusability, modularity, and extensibility of the code, whereas their disadvantages involve performance overhead and a certain added complexity. Knowledge of compile-time vs. runtime flow allows the developer to optimize their use, in inheritance handling, and good memory management.
FAQs
No, a constructor cannot be virtual because one cannot set up a vtable before a constructor is initialized for an object.
Yes, destructors should be virtual in base classes to ensure proper cleanup.
A vtable (virtual table) and vptr (virtual pointer) are used in C++ to manage virtual function calls.
In compile time, the constructor creates a vtable for classes with virtual methods. While in runtime, dynamically-vtable is resolved using the virtual functions.