In C++, a pure virtual function is a virtual function that is declared in a base class but has no implementation in that class. It is marked with the “pure virtual” specifier = 0
in its declaration. The presence of at least one pure virtual function in a class makes the class abstract, meaning it cannot be instantiated on its own. Instead, it serves as a base class for derived classes, and those derived classes must provide implementations for all the pure virtual functions declared in the base class.
Here is an example code to demonstrate pure virtual function in C++:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Shape { public: // Pure virtual function virtual void draw() const = 0; // Regular member function void commonFunction() { // Implementation for common functionality } }; class Circle : public Shape { public: // Implementation of the pure virtual function void draw() const override { // Implementation for drawing a circle } }; class Square : public Shape { public: // Implementation of the pure virtual function void draw() const override { // Implementation for drawing a square } }; |
In this example, the Shape
class has a pure virtual function draw()
which makes it an abstract class. The Circle
and Square
classes are derived from Shape
and provide concrete implementations for the draw()
function. Instances of the Shape
class cannot be created, but pointers or references to the Shape
class can be used to refer to objects of its derived classes.
Advantages of Pure Virtual Functions
Pure virtual functions contribute to the development of flexible and extensible code. These functions promote abstraction, polymorphism, and a clear separation between interfaces and their implementations. They are a fundamental feature of object-oriented design that encourages good software engineering practices.
Pure virtual functions in C++ offer several advantages such as:
Abstract Classes:
Pure virtual functions helps in creating abstract classes, which cannot be instantiated on their own but can be used as base classes for other classes. This promotes the concept of abstraction in object-oriented programming.
Abstract classes cannot be instantiated directly, but they serve as base classes for derived classes.
Enforcing Interface Contracts:
When a class declares pure virtual functions, it effectively defines an interface that derived classes must adhere to. This helps in enforcing a contract and ensures that all derived classes provide specific functionality.
Derived classes must provide concrete implementations for all pure virtual functions declared in the base class. Failure to do so results in a compilation error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Circle : public Shape { public: void draw() const override { // Implementation for drawing a circle } }; class Square : public Shape { public: // Error if draw() is not implemented here void draw() const override { // Implementation for drawing a square } }; |
Flexible Design:
Pure virtual functions provide a flexible design approach by allowing base classes to define a common interface while leaving the specific implementations to derived classes. This makes it easier to extend and modify code without affecting the existing interface.
Run-time Polymorphism:
The use of pure virtual functions is closely tied to dynamic polymorphism, where the appropriate function implementation is determined at runtime. This allows for more flexibility in selecting the correct method based on the actual type of the object being used.
1 2 | Shape* shapePtr = new Circle(); shapePtr->draw(); // Calls the draw() function of the Circle class |
Code Organization and Readability:
By using pure virtual functions, the code can be organized in a way that separates the interface ) from the implementation details. This enhances code readability and maintainability.
Override Checking:
When a class declares a pure virtual function, the compiler ensures that all derived classes provide an implementation for that function. This helps catch errors early in the development process and ensures that the derived classes adhere to the expected interface.