C++ Virtual Functions: In this tutorial, we will find out about the C++ virtual function and its use with the help of examples.
A virtual function is a member function in the base class that we hope to reclassify in inferred classes.
Fundamentally, a virtual capacity is used in the base class so as to ensure that the capacity is overridden. This particularly applies to situations where a pointer of base class focuses on an object of a derived class.
For instance, consider the code beneath:
class Base {
public:
void print() {
// code
}
};
class Derived : public Base {
public:
void print() {
// code
}
};
Later, if we create a pointer of Base type to point to an object of Derived class and call the print() function, it calls the print() function of the Base class.
In other words, the member function of Base is not overridden.
int main() {
Derived derived1;
Base* base1 = &derived1;
// calls function of Base class
base1->print();
return 0;
}
So as to keep away from this, we declare the print() function of the Base class as virtual by using the virtual watchword.
class Base {
public:
virtual void print() {
// code
}
};
Virtual functions are an integral part of polymorphism in C++
In this article, you will learn-
Example 1: C++ virtual Function
#include <iostream>
using namespace std;
class Base {
public:
virtual void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived derived1;
// pointer of Base type that points to derived1
Base* base1 = &derived1;
// calls member function of Derived class
base1->print();
return 0;
}
Output
Derived Function
Here, we have declared the print() function of Base as virtual.
So, this function is overridden even when we use a pointer of the Base type that points to the Derived object derived1.
C++ override Identifier
C++ 11 has given us another identifier override that is exceptionally valuable to evade bugs while using virtual capacities.
This identifier determines the member function of the derived classes that override the member capacity of the base class.
For instance,
class Base {
public:
virtual void print() {
// code
}
};
class Derived : public Base {
public:
void print() override {
// code
}
};
If we use a capacity prototype in Derived class and characterize that work outside of the class, at that point we use the accompanying code:
class Derived : public Base {
public:
// function prototype
void print() override;
};
// function definition
void Derived::print() {
// code
}
Use of C++ override
When using virtual capacities. it is conceivable to commit errors while announcing the part elements of the derived classes.
Using the override identifier prompts the compiler to show error messages when these mistakes are made.
Something else, the program will just assemble however the virtual capacity won’t be overridden.
A portion of these potential mistakes are:
- Functions with incorrect names: For example, if the virtual function in the base class is named print(), but we accidentally name the overriding function in the derived class as a pint().
- Functions with different return types: If the virtual function is, say, of void type but the function in the derived class is of int type.
- Functions with different parameters: If the parameters of the virtual function and the functions in the derived classes don’t match.
- No virtual function is declared in the base class.
Use of C++ Virtual Functions
Assume we have a base class Animal and determined classes Dog and Cat.
Assume each class has an information part named type. Assume these factors are instated through their particular constructors.
class Animal {
private:
string type;
... .. ...
public:
Animal(): type("Animal") {}
... .. ...
};
class Dog : public Animal {
private:
string type;
... .. ...
public:
Animal(): type("Dog") {}
... .. ...
};
class Cat : public Animal {
private:
string type;
... .. ...
public:
Animal(): type("Cat") {}
... .. ...
};
Presently, let us guess that our program expects us to make two public capacities for each class:
- getType() to return the value of type
- print() to print the value of type
We could make both these capacities in each class independently and abrogate them, which will be long and repetitive.
Or we could make getType() virtual in the Animal class, then create a single, separate print() function that accepts a pointer of Animal type as its argument. We can then use this single function to override the virtual function.
class Animal {
... .. ...
public:
... .. ...
virtual string getType {...}
};
... .. ...
... .. ...
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
This will make the code shorter, cleaner, and less repetitive.
Example 2: C++ virtual Function Demonstration
// C++ program to demonstrate the use of virtual function
#include <iostream>
#include <string>
using namespace std;
class Animal {
private:
string type;
public:
// constructor to initialize type
Animal() : type("Animal") {}
// declare virtual function
virtual string getType() {
return type;
}
};
class Dog : public Animal {
private:
string type;
public:
// constructor to initialize type
Dog() : type("Dog") {}
string getType() override {
return type;
}
};
class Cat : public Animal {
private:
string type;
public:
// constructor to initialize type
Cat() : type("Cat") {}
string getType() override {
return type;
}
};
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
int main() {
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
print(animal1);
print(dog1);
print(cat1);
return 0;
}
Output
Animal: Animal
Animal: Dog
Animal: Cat
Here, we have used the virtual function getType() and an Animal pointer ani in order to avoid repeating the print() function in every class.
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
In main(), we have created 3 Animal pointers to dynamically create objects of Animal, Dog and Cat classes.
// dynamically create objects using Animal pointers
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
We at that point call the print() work using these pointers:
- When print(animal1) is called, the pointer focuses on an Animal object. In this way, the virtual capacity in Animal class is executed within print().
2. When print(dog1) is called, the pointer points to a Dog object. So, the virtual function is overridden and the function of Dog is executed inside of print().
3. When print(cat1) is called, the pointer points to a Cat object. So, the virtual function is overridden and the function of Cat is executed inside of print().
Thanks for watching! We hope you found this tutorial helpful and we would love to hear your feedback in the Comments section below. And show us what you’ve learned by sharing your photos and creative projects with us.