Pure Virtual Function in C++

Pure Virtual Functions

Here, in this section, we will discuss pure virtual function in C++.

Pure Virtual functions are one of the ways we conceptualise Abstract classes. It is essentially a virtual function declared in the Parent Classes that doesn’t have any implementation and only has declaration.

  • Declared in Base Class
  • Is Virtual Function
  • Assigned to value 0
  • Doesn’t have implementation
  • Class containing Pure Virtual Function is called as Abstract Class
pure

Concept of Pure Virtual Functions

This was long demanded feature by programmers using other object-oriented languages –

What programmers wanted?

  1. Programmers most of the time wanted to just give good architecture of the code and create classes with no implementation.
  2. But, to fully use the inheritance concept without running the troubles of different instances of RunTime vs Compile time alternations in how code is performed.

How it was solved?

  1. With Pure Virtual functions, this problem was solved as it would guarantee the same result.
  2. That is implementation of the code will always be performed by Derived (Child) classes and they need only be declared in Base (Parent) classes.

Abstract Class

  • An abstract class is any class that just has declarations but no initialisations.
  • These initialisations and implementation details can be provided in the inherited derived classes.
  • Pure Virtual function helps us in achieving abstract classes.

We create a pure virtual function in the base class by –

  • Using virtual keyword before the function in the base class
  • Assigning it to 0
// An abstract class
class Test
{   
    // Data members of class
public:
    // Pure Virtual Function
    virtual void show() = 0;
    
   /* Other members */
};

Note – We can’t create objects of Abstract Classes or classes that contain Pure Virtual Functions.

Example of Pure Virtual Function Implementation

See how a pure virtual function without any implementation is created in the base class.

The result of the pointed object reference and derived class both are the same. They both call derived class function.

Run
#include <iostream>
using namespace std;

// This will be abstract class
// As it just has declarations and no definitions
// contains pure virtual functions
class Base
{
    public:
    // Pure virtual function created here
    virtual void display() = 0;
};

class Derived : public Base
{
    public:
    void display(){
        cout << "Inside the Derived Class\n";
    }
};
int main()
{
    // Pointer and Reference and basic derived class usage
    Derived derived1;
    Base *base;
    Derived derived2;

    derived1.display();
   
    base = &derived2;
    base->display();
    
    return 0;
}

Output –

Inside the Derived Class
Inside the Derived Class

Some interesting Facts about Pure Virtual Functions

1. Removal of Pure Virtual Function

Removing Pure Virtual implementation and providing a definition in the base class will lead to the base class function being called i.e. run-time polymorphism will happen.

Lets see an example below –

Run
#include <iostream>
using namespace std;

class Base
{
    public:
    // Pure virtual function removed
    // definition provided
    void display(){
        cout << "Inside the Base Class\n";
    }
    
};

class Derived : public Base
{
    public:
    void display(){
        cout << "Inside the Derived Class\n";
    }
};
int main()
{
    // Pointer and Reference and basic derived class usage
    Derived derived1;
    Base *base;
    Derived derived2;

    derived1.display();
   
    base = &derived2;
    base->display();
    
    return 0;
}

Output

Inside the Derived Class
Inside the Base Class

Since pure virtual function was removed and definition was provided to function in the base class, the base class function got called.

2. Creating Objects of Base Class (Pure Virtual Function case)

We can’t create a direct object of base class containing pure virtual function which is an abstract class.

We must create objects by –

  1. Derived class objects
  2. Or pointer reference of base class pointed towards the object of the derived class.

This was shown above in the first example.

Creating the Object of Base class will give an error. Example of this is show below –

Run
#include <iostream>
using namespace std;

class Base
{
    public:
    virtual void display() = 0;
};
class Derived : public Base
{
    public:
    void display(){
        cout << "Inside the Derived Class\n";
    }
};
int main()
{
    // IMPORTANT
    // this will cause error as we have created
    // object of base class
    Base base;
    base.display();
    
    // this alone wont have created any errors
    Derived derived;
    derived.display();
    
    // this also won't have created any errors
    // base class pointer referencing derived class object
    Base *base;
    Derived derived2;
    base = &derived2;
    base->display();
    
    return 0;
}

Output:

error: cannot declare variable 'base' to be of abstract type 'Base'

Both following ways to create a base pointer referenced towards derived objects are the same thing –

    // Method 1
    Base *base;
    Derived derived2;
    base = &derived2;
    base->display();


    // Method 2
    Base *base = new Derived();
    base->display();

3. Overriding base class Pure Virtual Function

Overriding the base class pure virtual function is necessary as if we don’t do that. Then, the derived class also is classified as an abstract class let us see what error comes if we do this –

Run
#include <iostream>
using namespace std;

class Base
{
    public:
    virtual void display() = 0;
};
class Derived : public Base
{
    public:
    // not defining base class virtual function (pure) here
    // thus overriding doesn't happen
    // error
};

int main()
{
    // this will cause error as we have created
    // object of base class
    Derived derived;
    derived.display();
    
    return 0;
}

Output

error: cannot declare variable 'derived' to be of abstract type 'Derived'
18 | Derived derived;
| ^~~~~~~

​4. The base class can have it’s own constructor

Let’s see an example for this –

Run
#include <iostream> 
using namespace std;

class Base
{
    public:
    int x, y;
    
    virtual void display() = 0;
    // base class can have its own constructor
    // even though we won't be able to create
    // objects of base class
    Base(){
        x=1; y=1;
    }
};

class Derived : public Base
{
    public:
    Derived(){
        x=10; y=10;
    }
    void display()
    {
        cout << "Values are -\n" << x << " and " << y;
}
};

int main()
{
    Derived derived;
    derived.display();
    
    return 0;
}

Output

Values are -
10 and 10

5. Illegal definition of Pure Virtual Function

Inline Definition of Pure Virtual Functions is illegal. But, still, you can define it outside the class

Run
#include <iostream> 
using namespace std;

class Base
{
    public:
    virtual void display() = 0;
};

// Pure Virtual definition, can define
// and wont cause error but wont be printed
void Base :: display()
{
    cout << "Pure Virtual definition\n";
}

class Derived : public Base
{
    public:
    void display(){
        cout << "Inside the Derived Class\n";
  }
};
int main()
{
    Derived derived1;
    derived1.display();
    
    return 0;
}

Output

Inside the Derived Class