The Differences Between Virtual and Pure Virtual Functions in C++

  1. Virtual Functions and Their Characteristics in C++
  2. Pure Virtual Functions and Abstract Types in C++

This article will describe the differences between virtual and pure virtual functions in C++.

Virtual Functions and Their Characteristics in C++

Virtual functions are closely associated with the concept of polymorphism. In C++, we can organize different classes in a linked hierarchy where they might be sharing some data members and having the same member functions exposed as the interface.

Generally, the classes that inherit some part of code from other classes are called derived classes, whereas the ones inherited from are the base classes. Note that sometimes these terms may be interchangeably used with parent-child or superclass-subclass names. The functions that can be overridden in derived classes are called virtual functions, and they are declared with the keyword virtual. Virtual functions have the same name within the given class hierarchy, and every derived class can implement its own definition of the function.

If the function is not overridden, the derived class object invokes the function defined in the base class. The following example program below demonstrates the basic usage of virtual functions by defining the print function in both the Engineer and Employee classes. Then we can implement some arbitrary function Func that accepts the reference to Employee and calls theprint function within the body.

Now, the Func implementation may change multiple times, but it will always call the corresponding print function based on the object that’s being passed as the parameter. We can add multiple derived classes in the Employee class hierarchy. Each of them may/may not implement the print function, but the Func function will accept their instances and invoke the correct virtual function.

#include <iostream>
#include <string>

using std::cout; using std::endl;
using std::string; using std::cin;

class Employee {
public:
    Employee(string fn, string ln) : first_name(std::move(fn)),
                                    last_name(std::move(ln)){}
    virtual void print() {
        cout << "name: " << first_name << "\n"
             << "last name: " << last_name << "\n";
    };

protected:
    string first_name, last_name;
};

class Engineer : public Employee {
public:
    Engineer(string fn, string ln, string sp) : Employee(std::move(fn), std::move(ln)),
            specialization(std::move(sp)) {}

    void print() override {
        Employee::print();
        cout << "specialization: " << specialization << "\n";
    }

private:
    string specialization;
};

void Func(Employee &em) {
    em.print();
}

int main() {

    Employee em1("Jim", "Jiao");
    Engineer eng1("Jin", "Baker", "Aerospace Engineering");

    Func(em1);
    cout << "\n";
    Func(eng1);

    return EXIT_SUCCESS;
}

Output:

name: Jim
last name: Jiao

name: Jin
last name: Baker
specialization: Aerospace Engineering

Pure Virtual Functions and Abstract Types in C++

On the other hand, we have the concept of pure virtual functions, which are declared similar to the regular virtual functions and include the notation = 0; at the end of the declaration. These functions essentially don’t have a definition in the base class, where they are declared first. Thus, they will be most likely defined in the derived classes.

The classes containing pure virtual functions are called abstract classes, and they are usually utilized to specify the interface for the derived classes. Note that abstract classes can not be directly instantiated.

The next code snippet implements the Triangle and Rectangle classes with the abstract base class Shape. In this case, we defined the printArea pure virtual function in both derived classes. Sometimes, a derived class might not define an inherited pure virtual function, making it another abstract class in the given class hierarchy. A derived class may inherit multiple pure virtual functions. If it does not define even one of them, abstract classification is applied to the class.

#include <iostream>
#include <string>
#include <vector>

using std::cout; using std::endl;
using std::string; using std::vector;

class Shape {
public:
    virtual void printArea() = 0;
};

class Triangle : public Shape {
public:
    Triangle(double b, double h) : base(b), height(h) {}

    void printArea() override {
        cout << (base * height) / 2.0;
    }

private:
    double base;
    double height;
};

class Rectangle : public Shape {
public:
    Rectangle(double i1, double i2) : edges({i1, i2}) {}

    void printArea() override {
        cout << edges[0] * edges[1];
    }

private:
    vector<double> edges;
};

int main() {

    Triangle t1(3, 5);
    t1.printArea();
    cout << "\n";

    Rectangle r1(3, 5);
    r1.printArea();
    cout << "\n";

    return EXIT_SUCCESS;
}

Output:

7.5
15
Contribute
DelftStack is a collective effort contributed by software geeks like you. If you like the article and would like to contribute to DelftStack by writing paid articles, you can check the write for us page.

Related Article - C++ Function

  • Pass Argument by Reference vs by Pointer in C++
  • The Difference Between Function Arguments and Parameters in C++