Table of Contents
Introduction
Welcome to the world of C++ programming, where we’ll unravel two important concepts: Virtual and Pure Virtual functions. Imagine them as tools to build super-flexible and strong programs. In this article, we’ll chat about why we even need them and how we can use them cleverly to create cool blueprints for classes. Think of these functions as magical ways to make your code more versatile. By the time we’re done, you’ll see how these functions add spice to your code, making it easier to change and grow. So, let’s dive in and make coding even more exciting!
What are Virtual Functions?
Virtual Functions: What Are They?
Imagine you have a team of superheroes in a computer program. Each superhero has a special power, like flying, super strength, or invisibility. Now, let’s say you want to organize a training session for your superheroes, but each one needs to practice their power differently. This is where virtual functions come in handy.
In programming, a virtual function is a concept that helps us manage different actions or behaviors for objects of the same class, just like our superheroes with different powers. It’s like giving each superhero their own customized training routine. Virtual functions are commonly used in object-oriented programming, where you define a base class with some functions, and then derived classes can customize those functions based on their specific needs.
Syntax and Simple Code Example:
#include <iostream>
class Superhero {
public:
virtual void usePower() {
std::cout << "Generic power used" << std::endl;
}
};
class FlyingHero : public Superhero {
public:
void usePower() override {
std::cout << "Flying power activated" << std::endl;
}
};
class StrongHero : public Superhero {
public:
void usePower() override {
std::cout << "Super strength activated" << std::endl;
}
};
int main() {
Superhero* hero1 = new FlyingHero();
Superhero* hero2 = new StrongHero();
hero1->usePower(); // Output: Flying power activated
hero2->usePower(); // Output: Super strength activated
delete hero1;
delete hero2;
return 0;
}
Output:
Flying power activated
Super strength activated
Explanation:
- We start by creating a base class
Superhero
with a virtual functionusePower()
. - Then, we create two derived classes,
FlyingHero
andStrongHero
, both inheriting fromSuperhero
. - In each derived class, we override the
usePower()
function to provide custom behavior for that specific hero type. - In the
main()
function, we create instances of both ‘FlyingHero
‘ and ‘StrongHero
‘ and assign them to pointers of type ‘Superhero
‘. - When we call the ‘
usePower()
‘ function using these pointers, the correct version of the function is invoked based on the actual object’s type (polymorphism). - Finally, we clean up the dynamically allocated objects using ‘
delete
‘ to prevent memory leaks.
What are Pure Virtual Functions?
Pure Virtual Functions in Simple Terms:
Imagine you’re building a blueprint for different types of vehicles like cars, bikes, and trucks. You know that all vehicles have certain common features like “start,” “stop,” and “honk.” However, the specific way each type of vehicle performs these actions can be different. For instance, a car starts with a key, a bike with a kick, and a truck with a button.
In programming, we can create a similar concept using “classes” and “functions.” A class is like a blueprint, and functions are the actions that the objects based on that blueprint can perform. A pure virtual function is like a placeholder for an action that must be defined by any class that uses the blueprint. It’s a way of saying, “Hey, any object based on this blueprint must have this function, but I won’t provide the details here.”
Syntax with Simple Code Example:
#include <iostream>
// Blueprint (abstract class)
class Vehicle {
public:
virtual void start() = 0; // Pure virtual function
virtual void stop() = 0; // Another pure virtual function
};
// Car class that follows the blueprint
class Car : public Vehicle {
public:
void start() override {
std::cout << "Car started with a key." << std::endl;
}
void stop() override {
std::cout << "Car stopped." << std::endl;
}
};
int main() {
Car myCar;
myCar.start();
myCar.stop();
return 0;
}
Output:
Car started with a key.
Car stopped.
Explanation:
- Pure virtual functions are used in C++ to create abstract classes, which are like blueprints for other classes.
- A pure virtual function is declared using the syntax:
virtual returnType functionName() = 0;
. - You cannot create objects of an abstract class because it has an incomplete function.
- Derived classes that inherit from an abstract class must provide definitions for all pure virtual functions.
- In the example code,
Vehicle
is an abstract class with two pure virtual functions:start
andstop
. - The
Car
class inherits fromVehicle
and provides specific implementations for the pure virtual functions. - In the
main
function, an object of theCar
class is created and itsstart
andstop
functions are called.
Differences between virtual and pure virtual functions in C++:
Aspect | Virtual Functions | Pure Virtual Functions |
---|---|---|
Definition | Virtual functions have a default implementation in the base class, but can be overridden by derived classes. | Pure virtual functions have no implementation in the base class and must be overridden by derived classes. |
Syntax | virtual returnType functionName() {...} | Virtual functions have a default implementation in the base class but can be overridden by derived classes. |
Usage | Used in both base and derived classes. | Used only in abstract base classes to create a blueprint for derived classes. |
Object Creation | Objects of the base class can be created. | Cannot create objects of the abstract class that contains pure virtual functions. |
Derived Implementation | Derived classes can choose to override the virtual function or use the base class implementation. | Derived classes must override all pure virtual functions; otherwise, they remain abstract. |
Completeness | A class with virtual functions can be instantiated on its own. | An abstract class with pure virtual functions cannot be instantiated on its own. |
Function Calling | Calls to virtual functions are resolved at runtime based on the actual object type. | Pure virtual functions are resolved at runtime like virtual functions, but the derived class’s implementation is called. |
Function Overloading | Can be overloaded with different parameter lists. | Can be overloaded with different parameter lists in the same way as virtual functions. |
Default Implementation in Base Class | Virtual functions can provide a default behavior in the base class that can be optionally overridden. | Pure virtual functions cannot have any implementation in the base class. |
Forcing Override | Derived classes can choose to override or not. | Derived classes must provide an implementation for all pure virtual functions. |
Examples of Virtual and Pure Virtual Functions in C++
Let’s look at some examples to see how virtual and pure virtual functions can be used in C++. We’ll provide the code, the expected output, and a step-by-step explanation of how virtual and pure virtual functions are used.
Example 1: Virtual Function
#include<iostream>
using namespace std;
class Animal {
public:
virtual void makeSound() {
cout << "The animal makes a sound" << endl;
}
};
class Dog : public Animal {
public:
void makeSound() override {
cout << "The dog barks" << endl;
}
};
int main() {
Animal* animal = new Dog();
animal->makeSound();
delete animal;
return 0;
}
Output:
The dog barks
Explanation:
- The code defines a base class
Animal
with a virtual functionmakeSound()
that outputs a generic animal sound. - The
Dog
class inherits fromAnimal
and overrides themakeSound()
function to output “The dog barks”. - A pointer of type
Animal
is created and assigned a dynamically allocatedDog
object. - The
makeSound()
function is called on the pointer, invoking the overridden function inDog
to output “The dog barks”. - The dynamically allocated object is deleted to free the memory.
Example 2: Pure Virtual Function
#include<iostream>
using namespace std;
class Shape {
public:
virtual void draw() = 0; // Pure virtual function
};
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing a circle" << endl;
}
};
int main() {
Shape* shape = new Circle();
shape->draw();
delete shape;
return 0;
}
Output:
Drawing a circle
Explanation:
- The code defines an abstract base class
Shape
with a pure virtual functiondraw()
. - The
Circle
class inherits fromShape
and overrides thedraw()
function to draw a circle. - A pointer of type
Shape
is created and assigned a dynamically allocatedCircle
object. - The
draw()
function is called on the pointer, invoking the overridden function inCircle
to draw a circle. - The dynamically allocated object is deleted to free the memory.
Advantages and Disadvantages of virtual and pure virtual functions:
Aspect | Virtual Functions | Pure Virtual Functions |
---|---|---|
Advantages | – Provides a default implementation that can be used by derived classes. – Offers flexibility for derived classes to override the function if needed. – Allows object creation of the base class. | – Ensures derived classes implement a specific function. – Defines a clear contract for derived classes to follow. – Enables runtime polymorphism. |
Disadvantages | – Can lead to unintended behavior if not properly overridden in derived classes. – Changes in base class implementation can impact multiple derived classes. – Allows object creation of the base class. | – Requires derived classes to provide an implementation, reducing flexibility. – Cannot create objects of the base class with pure virtual functions. – Increases complexity due to mandatory function overrides. |
Key Takeaways
- Blueprint for Flexibility: Virtual functions allow you to create a blueprint in a base class that can be customized by derived classes. This enables you to define a common interface while accommodating different implementations.
- Runtime Polymorphism: Virtual functions enable polymorphism, where you can call a function on a base class pointer or reference, and the appropriate derived class function will be executed at runtime.
- Pure Virtual Functions: By making a function pure virtual using the
= 0
syntax, you create a placeholder that must be implemented by any derived class. This enforces consistency in derived classes’ behavior. - Abstract Classes: When a class contains pure virtual functions, it becomes an abstract class, meaning you can’t create objects of that class. Abstract classes are used as base blueprints for other classes.
- Extensibility: Using virtual and pure virtual functions, you can build systems that are easily extendable. You can add new derived classes with unique behaviors without needing to modify existing code, promoting a modular and maintainable design.
Conclusion
In conclusion, virtual and pure virtual functions are like the recipe of a chef in C++. By understanding how to use virtual and pure virtual functions, you can write better, more flexible programs. So keep practicing, and soon you’ll be a pro at using virtual and pure virtual functions!
FAQs
- What are virtual and pure virtual functions in C++?
Virtual functions are member functions in the base class that you can override in a derived class. Pure virtual functions are functions in an abstract class that don’t have an implementation in the base class. - Why do we use virtual and pure virtual functions in C++?
We use virtual and pure virtual functions in C++ to provide a structure for other functions. They ensure that every derived class provides certain functionalities. - How do we use virtual and pure virtual functions in C++?
We use virtual functions by declaring them in the base class and overriding them in the derived class. We use pure virtual functions by declaring them in the abstract class with ‘= 0’ at the end. Derived classes must then provide the implementation for these functions. - Can using virtual and pure virtual functions make code more confusing?
Yes, if you use virtual and pure virtual functions incorrectly, it can make your code more complex and harder to read. It’s important to understand when and how to use virtual and pure virtual functions effectively. - What are some examples of using virtual and pure virtual functions in C++?
Some examples include using virtual functions to make different types of animal objects make different sounds, or using pure virtual functions to draw different types of shape objects differently.