In C++, a pure virtual function is a virtual function declared in the base class that necessitates being overridden in the derived class. The function declaration concludes with = 0, signaling that it is devoid of any default implementation within the class body. Nevertheless, it can be defined externally to the class if necessary.
Any subclass that extends the base class is required to implement the method. When a class contains at least one pure virtual function, it is classified as abstract and cannot be instantiated. Abstract classes act as templates for other classes, guaranteeing that the subclasses offer the essential functionality needed.
Syntax
It has the following syntax.
virtual returnType function_name() = 0;
In this particular syntax,
- The term "virtual" signifies the function's polymorphic nature.
- The "= 0" notation denotes that the function is purely virtual, implying that it is abstract and lacks an implementation in the base class.
C++ Pure Virtual Function Example
Let's consider an example to demonstrate Pure Virtual Function in C++.
Example
#include <iostream>
using namespace std; //using standard namespace
class Shape
{
public: //access specifier
virtual double calculatingArea() = 0;
virtual ~Shape() {}
};
class Circle : public Shape
{
double radius;
public:
Circle(double r) : radius(r) {}
double calculatingArea() override
{
return 3.14159 * radius * radius;
}
};
class Rectangle : public Shape
{
double length, width;
public:
Rectangle(double len, double wid) : length(len), width(wid) {}
double calculatingArea() override
{
return length * width;
}
};
class Triangle : public Shape
{
double base, height;
public:
Triangle(double b, double h) : base(b), height(h) {}
double calculatingArea() override
{
return 0.5 * base * height;
}
};
int main() //main function
{
Shape* s[3];
s[0] = new Circle(7);
s[1] = new Rectangle(13, 15);
s[2] = new Triangle(6, 9);
cout << "The area of the Circle is: " << s[0]->calculatingArea() << endl;
cout << "The area of the Rectangle is: " << s[1]->calculatingArea() << endl;
cout << "The area of the Triangle is: " << s[2]->calculatingArea() << endl;
for (int q = 0; q < 3; ++q)
{
delete s[q];
}
return 0;
}
Output:
The area of the Circle is: 153.938
The area of the Rectangle is: 195
The area of the Triangle is: 27
Explanation:
In this instance, we demonstrate the concept of runtime polymorphism by implementing a pure virtual function called calculatingArea within the abstract base class Shape. The Circle, Rectangle, and Triangle subclasses then redefine this method to compute and display their individual areas.
Characteristics of Pure Virtual Functions
Pure virtual functions have several characteristics in C++ . Some main characteristics are as follows:
- No implementation in the base class: A pure virtual function in the base class is stated as = 0, which indicates that no implementation is applied. Its main purpose is to serve as a placeholder, which indicates that derived classes must be implemented.
- Defines an abstract class: If a class contain only one pure virtual function, it becomes abstract.
- Ensures a common interface: Pure virtual functions provide a standardized interface. They require all subclasses to implement particular functions, which helps to maintain consistency between types derived from the same base.
- Runtime Polymorphism: Pure virtual functions use dynamic (late) binding, which means the appropriate function is called based on the actual object type at runtime, particularly when accessed through base class pointers or references.
- Acts as a Contract: A pure virtual function is effectively a contract that needs any class that inherits from the base to implement the stated functions. It helps to prevent missing or inconsistent method definitions during development.
- Checked at compile time: The compiler applied the implementation rules. If a subclass fails to override a needed function, an error is thrown at build time, which helps to reduce the runtime surprises and increases dependability.
Interesting Facts about Pure Virtual Functions in C++
There are a number of intriguing aspects regarding abstract functions in C++. A few of these are outlined below:
1) Removal is not permitted in derived classes
In C++, a pure virtual function defined in a parent class cannot be omitted or left unimplemented in a child class. Each derived class must supply a concrete implementation to avoid being considered abstract.
#include <iostream>
class Parent
{
public:
virtual void show() = 0; // Pure virtual function
};
class Child : public Parent
{
// Missing override leads to a compilation error
// void show() {} // Required override
};
int main() //main function
{
return 0;
}
Explanation:
In this instance, the subclass needs to redefine the abstract function to transition into a fully implemented (non-abstract) class.
2) Cannot instantiate abstract classes
Any class that contains at least one pure virtual function is classified as abstract and cannot be instantiated directly.
Example
#include <iostream>
class Parent
{
public:
virtual void show() = 0;
};
int main() //main function
{
Parent obj_1;
// Error: Abstract class cannot be instantiated
return 0;
}
Output:
main.c:9:12: error: cannot declare variable 'obj_1' to be of abstract type 'Parent'
Explanation:
In this instance, the abstract class instances are unfinished because of omitted implementations and cannot be instantiated.
3) Overriding Is Mandatory in Derived Classes
In C++, it is essential for the derived class to provide implementations for all pure virtual functions. Failure to do so will result in the derived class being abstract, preventing its instantiation.
Example
#include <iostream>
using namespace std; //using standard namespace
class Parent
{
public:
virtual void display() = 0;
};
class Child : public Parent
{
public:
void display() override
{
cout << "Child implementation\n";
}
};
int main() //main function
{
Child obj_1;
obj_1.display();
return 0;
}
Output:
Child implementation
Explanation:
In this instance, the subclass redefines the method, enabling it to be instantiated and employed.
4) Base Class Can Have Constructor
In C++, even if a base class includes abstract virtual functions, it is still possible to define a constructor. This particular constructor gets called during the creation of an instance of a derived class.
Example
#include <iostream>
using namespace std; //using standard namespace
class Parent
{
public: //access specifier
Parent()
{
cout << "Parent constructor\n";
}
virtual void run() = 0;
};
class Child : public Parent
{
public:
void run() override
{
cout << "Child run function\n";
}
};
int main() //main function
{
Child obj_1; //creating an objects
obj_1.run();
return 0;
}
Output:
Parent constructor
Child run function
Explanation:
In this instance, the initial step involves invoking the constructor of the parent class, succeeded by the execution of the function within the child class.
5) Illegal to Define Pure Virtual Function in Base Class
In C++, it is not allowed to provide an inline definition for a pure virtual function inside the base class. However, it is permissible to define it outside the class.
Example
#include <iostream>
using namespace std; //using namespace standard
class Base
{
public: //access specifier
virtual void display() = 0;
};
// Pure Virtual definition can define
// and wont cause error but wont be displayed
void Base :: display()
{
cout << "Pure Virtual definition\n";
}
class Derived : public Base
{
public:
void display(){
cout << "Inside the Derived Class\n";
}
};
int main() //main function
{
Derived der1;
der1.display();
return 0;
}
Output:
Compilation Error
Explanation:
In this instance, the abstract virtual method is designed to be defined in subclasses, rather than the base class directly.
Advantages of Pure Virtual Functions
Several advantages of pure virtual functions in C++ are as follows:
- Enforce Interface Consistency: All derived classes must implement particular methods and maintain a consistent structure.
- Enable Polymorphism: It enables Polymorphism for dynamic binding, which allows objects to behave differently dependent on their type at runtime.
- Avoid Object Creation: Abstract classes with pure virtual functions cannot be instantiated, which prevents misuse.
- Modularity: It promotes modularity by separating the interface from implementation, which allows for simpler extension and maintenance.
- Compile-Time Safety: It improves compile-time safety by detecting unimplemented functions early on, which reduces runtime errors.
- Support Design Patterns: It creates the basis for patterns like the Factory Method and Template Method, which enables scalable designs.
Disadvantages of Pure Virtual Functions
Several disadvantages of pure virtual functions in C++ are as follows:
- Adds Complexity: Overriding class hierarchies can complicate code maintenance.
- Rigid Interface: Changing or removing pure virtual functions can cause issues with existing subclasses.
- No Shared Defaults: Base classes cannot provide default logic, which leads to code duplication.
- Minor Runtime cost: Dynamic dispatch has a minimal impact on performance-critical applications.
- Tight Coupling: Any changes in the base class necessitate updates to all subclasses, which increases compile-time dependence.
- Limited Scope: It is suitable for polymorphic designs but not essential for simpler or non-hierarchical structures.
C++ Pure Virtual Function MCQs
1) Which of the following options is the best definition of a C++ pure virtual function?
- virtual void show;
- void show = 0
- virtual void show = 0
- void show
2) What is the point of declaring a pure virtual function within a class?
- To establish default behavior.
- To construct global variables.
- To prohibit function-overriding
- Require derived classes to override the function.
3) What happens when a derived class does not override a pure virtual function in C++?
- The derived class becomes abstract
- The function is automatically inherited
- The base class is destroyed
- The program runs with a warning
4) Which of the following options claims about abstract classes is correct in C++?
- There are no constructors
- No member functions are available
- They can be used directly
- There should be at least one pure virtual function
5) Why does C++ impose compile-time tests on pure virtual functions?
- To prevent memory leaks
- To detect missing implementations early
- To reduce compiler speed
- To enable object slicing
To identify absent implementations in the early stages.