Pure Virtual Function in C++ – The Complete Guide
Did you know that It is almost impossible to make an implementation of every function in a base class within a pure virtual function in C++? A pure virtual function in C++ has no implementation associated with it except when being declared. It doesn’t contain any code belonging to its base class and the functionality for its specific case must be provided by an inherited derived class instead. In the following sections, we will be exploring the concept of a pure virtual function in C++, its characteristics, and interesting facts about it.
What is a Pure Virtual Function in C++?
A pure virtual function in C++ does not have an implementation yet it can be declared. Pure virtual functions do not retain any definition related to their base class, the only way it can be implemented is by assigning zero (0) in the declaration itself. Therefore, classes that contain one or more functions cannot be used for defining objects, for this reason, these classes are known as “abstract classes.” In order for abstract classes to work properly, all derived subclasses must provide implementations of these pure virtual functions.
Syntax:
virtual void display() = 0;
virtual void display() {}
Here is a sample of a pure virtual function in C++ code:
// Definition of an abstract framework
class AbstractModule {
// Class properties
public:
// Mandatory Abstract Operation
virtual void performAction() = 0;
/* Additional class components */
};
For comprehensive knowledge of pure virtual functions in C++, you can take an online course on programming in C++.
Below are the characteristics of a virtual function:
1. The function of a pure virtual function is empty because the base class is not defined.
2. A pure virtual function class can not be directly used to create objects independently. It is also known as an abstract class. Therefore any class that possesses a pure virtual function doesn’t have the ability to create an object of that class.
3. A virtual class cannot perform any task. Basically, the derived class makes the function implementation, and the virtual class provides templates.
4. For a virtual class to be useful to programmers, they will have to use the derived class to redefine the pure virtual function so as to define it in the base class.
Must-Know Facts About Pure Virtual Functions in C++
1. If a class possesses at least one pure virtual function it is considered to be abstract.
Example:
The C++ code below has a test in an abstract class because its pure virtual function is shown as ().
// Example illustrating an abstract concept using C++
#include <iostream>
using namespace std;
class AbstractShape {
// Private attribute
int sides;
public:
// Pure virtual method
virtual void displayInfo() = 0;
// Accessor method for sides
int getNumSides() { return sides; }
};
int main(void)
{
// Error: Cannot create an instance of an abstract class
AbstractShape shape;
return 0;
}
Output
The provided C++ code attempts to illustrate an abstract concept using a class named AbstractShape. However, there are a couple of issues in the code:
- The class AbstractShape is defined with a pure virtual method displayInfo(), making it an abstract class.
- An attempt is made to create an instance of the AbstractShape class in the main function, which is not allowed due to the class being abstract.
When this code is compiled, it will result in a compilation error due to the attempt to create an instance of an abstract class. The error message will typically indicate that an object of an abstract class type cannot be created.
The output of the code will be a compilation error message similar to:
error: cannot declare variable 'shape' to be of abstract type 'AbstractShape'
In the above code, the error arises because you cannot directly instantiate an abstract class. Abstract classes are meant to be base classes that provide a common interface for derived classes to implement. They cannot be instantiated on their own because they contain pure virtual methods, which don’t have a concrete implementation in the base class. Instead, you can create derived classes that inherit from the abstract class and provide concrete implementations for the pure virtual methods.
2. We can store the addresses of a particular type of abstract class in both pointer and reference variables, however, we are unable to instantiate or call any functions on this object because they lack implementation details due to being abstract classes.
Example:
#include <iostream>
using namespace std;
class Shape {
public:
// pure virtual method
virtual void displayInfo() = 0;
};
class Circle : public Shape {
public:
// implementation of the pure virtual method
void displayInfo() { cout << "Inside Circle\n"; }
};
int main() {
// creating a pointer of type
// Shape pointing to an object
// of type Circle
Shape* shapePtr = new Circle();
// calling the displayInfo() method using the
// pointer
shapePtr->displayInfo();
return 0;
}
Output:
Inside Circle
Explanation: The code defines an abstract class Shape with a pure virtual method displayInfo(). Then, a class Circle is derived from Shape and provides an implementation for the displayInfo() method. In the main function, a pointer of type Shape named shapePtr is created and assigned to a new Circle object. When shapePtr->displayInfo() is called, it invokes the displayInfo() method of the Circle class, resulting in the output “Inside Circle”.
3. In C++, a struct keyword can be used to define an abstract class as well. This data type allows for the creation of classes that employ virtual functions and interfaces with no implementation details included in them. Abstract classes are useful when designing complex systems because they enable developers to break down their code into logical components that have clearly defined relationships between each other but don’t require any actual implementations until later stages in development.
Example:
#include <iostream>
using namespace std;
// Abstract class defined using struct
struct ShapeClass {
virtual void Draw() = 0; // Pure virtual function
};
// Concrete class Rectangle derived from ShapeClass
struct Rectangle : ShapeClass {
void Draw() override {
cout << "Drawing a rectangle." << endl;
}
};
// Concrete class Circle derived from ShapeClass
struct Circle : ShapeClass {
void Draw() override {
cout << "Drawing a circle." << endl;
}
};
int main() {
Rectangle rectangle;
Circle circle;
ShapeClass* shape1 = &rectangle;
ShapeClass* shape2 = &circle;
shape1->Draw();
shape2->Draw();
return 0;
}
Output:
Drawing a rectangle.
Drawing a circle.
Explanation: In the code, an abstract class ShapeClass is defined using the struct keyword, containing a pure virtual function Draw(). Two concrete classes, Rectangle and Circle, are derived from ShapeClass and provide their implementations of the Draw() method. In the main function, instances of Rectangle and Circle are created. Pointers to the abstract base class ShapeClass are used to call the Draw() method, which is overridden in the derived classes. As a result, “Drawing a rectangle.” and “Drawing a circle.” are displayed in the output.
Conclusion
The use of pure virtual functions in C++ is essential for attaining abstraction and developing standard interfaces between class hierarchies. When it isn’t feasible to offer defined implementations for all the procedures within a base class as a result of various requirements throughout derived classes, pure virtual functions provide an efficient resolution. Designating a function using the “virtual” keyword together with assigning it 0 determines that base class as abstract, rendering it impossible to create instances from this specific type.
In essence, imposing conditions on derived classes via the utilization of pure virtual functions plays an important role in crafting dynamic structural schemes that maximize efficiency without sacrificing flexibility.