logo codesdope

Virtual and abstract


Before going to virtual function, let's first have a look at early binding and late binding.

Binding means matching the function call with the correct function definition by the compiler. It takes place either at compile time or at runtime.

Early Binding


In early binding, the compiler matches the function call with the correct function definition at compile time. It is also known as Static Binding or Compile-time Binding. By default, the compiler goes to the function definition which has been called during compile time. So, all the function calls you have studied till now are due to early binding.

You have learned about function overriding in which the base and derived classes have functions with the same name, parameters and return type. In that case also, early binding takes place.

In function overriding, we called the function with the objects of the classes. Now let's try to write the same example but this time calling the functions with the pointer to the base class i.e., refernce to the base class' object.

#include <iostream>

using namespace std;

class Animals
{
	public:
		void sound()
		{
			cout << "This is parent class" << endl;
		}
};

class Dogs : public Animals
{
	public:
		void sound()
		{
			cout << "Dogs bark" << endl;
		}
};

int main()
{
	Animals *a;
	Dogs d;
	a= &d;
	a -> sound();   //  early binding
	return 0;
}
Output
This is parent class

Now in this example, we created a pointer a to the parent class Animals. Then by writing a= &d , the pointer 'a' started referring to the object d of the class Dogs.
a -> sound(); - On calling the function sound() which is present in both the classes by the pointer 'a', the function of the parent class got called, even if the pointer is referring to the object of the class Dogs.

This is due to Early Binding. We know that a is a pointer of the parent class referring to the object of the child class. Since early binding takes place at compile-time, therefore when the compiler saw that a is a pointer of the parent class, it matched the call with the 'sound()' function of the parent class without considering which object the pointer is referring to.

Late Binding


In the case of late binding, the compiler matches the function call with the correct function definition at runtime. It is also known as Dynamic Binding or Runtime Binding.

In late binding, the compiler identifies the type of object at runtime and then matches the function call with the correct function definition.

By default, early binding takes place. So if by any means we tell the compiler to perform late binding, then the problem in the previous example can be solved.

This can be achieved by declaring a virtual function.

Virtual function


Virtual Function is a member function of the base class which is overridden in the derived class. The compiler performs late binding on this function.

To make a function virtual, we write the keyword virtual before the function definition.

#include <iostream>

using namespace std;

class Animals
{
	public:
		virtual void sound()
		{
			cout << "This is parent class" << endl;
		}
};

class Dogs : public Animals
{
	public:
		void sound()
		{
			cout << "Dogs bark" << endl;
		}
};

int main()
{
	Animals *a;
	Dogs d;
	a= &d;
	a -> sound();
	return 0;
}
Output
Dogs bark

Since the function sound() of the base class is made virtual, the compiler now performs late binding for this function. Now, the function call will be matched to the function definition at runtime. Since the compiler now identifies pointer a as referring to the object 'd' of the derived class Dogs, it will call the sound() function of the class Dogs.

If we declare a member function in a base class as a virtual function, then that function automatically becomes virtual in all of its derived classes.

If we make any function inside a base class virtual, then that function becomes virtual in all its derived classes. This means that we don't need to declare that function as virtual separately in its derived classes.

We can also call private function of derived class from a base class pointer by declaring that function in the base class as virtual.

Compiler checks if the members of a class are private, public or protected only at compile time and not at runtime. Since our function is being called at runtime, so we can call any type of function, private or public as shown in the following example.

#include <iostream>

using namespace std;

class Animals
{
	public:
		virtual void sound()
		{
			cout << "This is parent class" << endl;
		}
};

class Dogs : public Animals
{
	private:
		virtual void sound()
		{
			cout << "Dogs bark" << endl;
		}
};

int main()
{
	Animals *a;
	Dogs b;
	a = &b;
	a->sound();
	return 0;
}
Output
Dogs bark

Since the same function (virtual function) having different definitions in different classes is called depending on the type of object that calls the function, this is also a part of Polymorphism.

Pure Virtual Function


Pure virtual function is a virtual function which has no definition. Pure virtual functions are also called abstract functions.

To create a pure virtual function, we assign a value 0 to the function as follows.

virtual void sound() = 0;

Here sound() is a pure virtual area.

Abstract Class


An abstract class is a class whose instances (objects) can't be made. We can only make objects of its subclass (if they are not abstract). Abstract class is also known as abstract base class.

An abstract class has at least one abstract function (pure virtual function).

Let's look at an example of abstract class.

Suppose there are some employees working in a firm. The firm hires only two types of employees- either driver or developer. Now, you have to develop a software to store information about them.

So, here is an idea - There is no need to make objects of employee class. We will make objects to only driver or developer. Also, both must have some salary. So, there must be a common function to know about salary.

This need will be best accomplished with abstract class.

So, we can make 'Employee' an abstract class and 'Developer' and 'Driver' its subclasses.

#include <iostream>

using namespace std;

class Employee                    //  abstract base class
{
	virtual int getSalary() = 0;    // pure virtual function
};

class Developer : public Employee
{
	int salary;
	public:
		Developer(int s)
		{
			salary = s;
		}
		int getSalary()
		{
			return salary;
		}
};

class Driver : public Employee
{
	int salary;
	public:
		Driver(int t)
		{
			salary = t;
		}
		int getSalary()
		{
			return salary;
		}
};

int main()
{
	Developer d1(5000);
	Driver d2(3000);
	int a, b;
	a = d1.getSalary();
	b = d2.getSalary();
	cout << "Salary of Developer : " << a << endl;
	cout << "Salary of Driver : " << b << endl;
	return 0;
}
Output
Salary of Developer : 5000
Salary of Driver : 3000

The getSalary() function in the class Employee is a pure virtual function. Since the Employee class contains this pure virtual function, therefore it is an abstract base class.
Since the abstract function is defined in the subclasses, therefore the function 'getSalary()' is defined in both the subclasses of the class Employee.
You must have understood the rest of the code.

Subclasses of an abstract base class must define the abstract method, otherwise, they will also become abstract classes.
In an abstract class, we can also have other functions and variables apart from pure virtual function.

Let's see one more example of abstract base class.

#include <iostream>

using namespace std;

class Animals
{
	public:
		virtual void sound() = 0;
};

class Dogs
{
	public:
		void sound()
		{
			cout << "Dogs bark" << endl;
		}
};

class Cats
{
	public:
		void sound()
		{
			cout << "Cats meow" << endl;
		}
};

class Pigs
{
	public:
		void sound()
		{
			cout << "Pigs snort" << endl;
		}
};

int main()
{
	Dogs d;
	Cats c;
	Pigs p;
	d.sound();
	c.sound();
	p.sound();
	return 0;
}
Output
Dogs bark
Cats meow
Pigs snort

Interface


Interface or Interface class is a class which is the same as abstract class with a difference that all its functions are pure virtual and it has no member variables. Its derived classes must implement each of its virtual functions i.e., provide definition to each of the pure virtual functions of the base class.

Like an abstract class, we can't create objects of an interface.

We can also say that interface is an abstract class with no member variables and all its member functions pure virtual.

Name of an interface class often begins with the letter I.

Let's see an example of it.

class IShape
{
    public:
        virtual getArea() = 0;
        virtual getPerimeter() = 0;
};

IShape is an interface because it contains only pure virtual functions.

#include <iostream>

using namespace std;

class IShape
{
	public:
		virtual int getArea() = 0;
		virtual int getPerimeter() = 0;
};

class Rectangle : public IShape
{
	int length;
	int breadth;
	public:
		Rectangle(int l, int b)
		{
			length = l;
			breadth = b;
		}
		int getArea()
		{
			return length * breadth;
		}
		int getPerimeter()
		{
			return 2*(length + breadth);
		}
};

class Square : public IShape
{
	int side;
	public:
		Square(int a)
		{
			side = a;
		}
		int getArea()
		{
			return side * side;
		}
		int getPerimeter()
		{
			return 4 * side;
		}
};

int main()
{
	Rectangle rt(7, 4);
	Square s(4);
	cout << "Rectangle :" << endl;
	cout << "Area : " << rt.getArea() << " Perimeter : " << rt.getPerimeter() << endl;
	cout << "Square :" << endl;
	cout << "Area : " << s.getArea() << " Perimeter : " << s.getPerimeter() << endl;
	return 0;
}
Output
Rectangle :
Area : 28 Perimeter : 22
Square :
Area : 16 Perimeter : 16

So we just saw that IShape is an interface with two pure virtual functions. These virtual functions are implemented (defined) in its subclasses Rectangle and Square according to their requirements.

So, an interface is just an abstract class with all pure virtual methods.

Everything is practice

Share what you know
Doubt? Ask question
Close

Welcome.please sign up.

Close

Welcome.please login.