본문 바로가기

Programming/C++ Basic

[Basic C++] 16 - Data Structure in C++ : Class Virtual Function

C++ class series : previous postings

2020/06/13 - [Programming/C++] - [Basic C++] 15 – Data Structure in C++ : Class Single Inheritance

2020/06/13 - [Programming/C++] - [Basic C++] 14 – Data Structure in C++ : Class Constructor and Destructor

2020/06/04 - [Programming/C++] - [Basic C++] 13 – Data Structure in C++ : What is a CLASS, definition, and explanation

 

 

1. Definition of Virtual Function

A virtual function is a member function of a class that derived classes also have within so that the compiler is "confused" by the same multiple choices; which one to call when the function is passed to another function.

 

As we have already studied in the earlier posting, a class member with the same name as the one in a base class can be defined in a derived class lie below,

 

Code example 1

class A
{
public:
	 int a;
}

class B : public A
{
public:
	int a;
    int b = A::a;
}

 

In order to call the class member in A, the scope resolution operator (::) is used to let the compiler know which "a" to call. This is because those two variables are defined within two different namespaces. Now let's see the next example below,

 

Code example 2

#include <iostream>

class A
{
public:
	void print_name()
	{
		std::cout << "Class A" << std::endl;
	}
};

class B : public A
{
public:
	void print_name()
	{
		std::cout << "Class B" << std::endl;
	}
};

void print_name(A* p)
{
	p->print_name();
}

int main()
{
	A* pa = new A;
	B* pb = new B;

	print_name(pa);
	print_name(pb);
}

 

Figure 1 Result of code example 2

In this example, we create two class pointers and dynamically allocate them to the class objects A and B. Thus, the pointer "pa" points to the object of A, and the pointer "pb" points to the object of B. Class A is the base class of class B, and both of them have the function with the same name to print a message.

 

Another "print_name" function is declared to get the class member function by accepting a class pointer argument. This argument is a class pointer of A.

 

What we expected for the result was to get "Class A" and "Class B". However, the actual result was "Class A" and another "Class A". What happened here?

 

What really happened here was that the compiler was confused by two class member functions wit the same name and form. Therefore, in order to help the compiler make the right decision, we should help it to recognize the right function to call.

 

 

Figure 2 Default behavior of C++ compiler when it faces "same name functions" situation

 

When we pass the pointer that points to the object of class B to the function "print_name", the default behavior of the compiler is to recognize the argument's data type. Thus the function considers any object passed to the function as the objects of class A, which is the Behavior (1) in Figure 2. 

 

Then how can we enforce the compiler to get the class member function in class B object? (Behavior 2) This is why we need a "Virtual Function". By adding the "virtual" keyword at the front of the function in class A, we can redefine the same function in derived classes and call it without causing confusion to the compiler.

 

Code example 3

#include <iostream>

class A
{
public:
	virtual void print_name()
	{
		std::cout << "Class A" << std::endl;
	}
};

class B : public A
{
public:
	void print_name() override
	{
		std::cout << "Class B" << std::endl;
	}
};

void print_name(A* p)
{
	p->print_name();
}

int main()
{
	A* pa = new A;
	A* pb = new B;

	print_name(pa);
	print_name(pb);
}

Figure 3 Result of Code example 3

 

The keywords "virtual" and "override" are used within the example. The virtual keyword informs the compiler that the virtual function is going to be redefined in derived classes. In addition, the override keyword is added to the function in the derived class to clarify the fact the function is overridden. Although "override" is an optional keyword, it's a good practice to write it explicitly to increase the readability of your code.

 

A class that declares or inherits virtual functions is referred to as a "Polymorphic Class". The word "Polymorphic" is from the word "Polymorphism", and it is one of the most important programming concepts in OOP. I am going to talk about this at the next posting.