This article is all about Virtual Function in Java and C++ and how they are implemented and used in both the languages, what is the default behaviour of both the languages in respect to the virtual functions and how the functions can be made virtual and non-virtual.
In object-oriented programming, a virtual function or virtual method is a function or method whose behaviour can be overridden within an inheriting class by a function with the same signature to provide the polymorphic behavior.
In more simple words, lets suppose there is a Base class which have a function name print() and there is another Child class which is inherited from Base class and also have a function name print(). Now, if function of Base class i.e Base::print() is non virtual then function of child class i.e Child::print() will not override the function of Base class during runtime. And if Base::print() is made virtual then Child::print() function will override the Base class function. Examples related to these are shown in the following sections.
Virtual Function in C++ :
In c++, all the class member functions are non-virtual by default. They can be made virtual by using the virtual keyword in the function signature. As stated above if the function of base class is made virtual then the function of Derived or Child class?s function with same name can override the Base class?s function.
Examples:
Non Virtual function in C++ : ?
Code :
In the code, Base::print() is non-virtual function. Now, lets look at what happened in the main function :
In Line #20, we declared an object b of Base class which creates an object of Base class and when we called the function print on b in line #21 it simply calls print function of Base class, same is happening in line #23 and line #24 ? this is very simple. But, in line #26 we declared an object b1 of Base class but assigned an object of Child class i.e c to it. And when we call print function from b1 object, print function of Base class is called even when it is assigned a child object. This happens because for every Child class object created there is an Base class object created implicitly. So when we assigned an object of Child class c to b1 (using pass by value), it simply copies the Base class object created as a parent of c to the Base class object b1, this concept is called object slicing. As b1 object only contains Base class data members so while calling print(), print() of Base class is called. Same is happening in line #29 and #30 in this particular case but there is lot of difference between case 3 and current case 4 which we will see in upcoming examples. Last case is similar to case #3.
Virtual function in C++ : ?
Code:
Here, print function of Base class is made virtual by adding a keyword virtual in the function signature. Case 1, Case 2, Case 3 and Case 5 is similar to the above example. In case 4, function called is of Child class not of Base class where we saw in above example that function of Base class i.e Base::print() is called.
So what is different here?
Here, Base::print() is overridden by the Child::print() so when we are calling print function using pointer to Base class object, Child::print() is called. So the question rises here is that why it is not happening in the case 3 and case 5 where Base::print() is being called not Child::print()? The answer is runtime polymorphism. In case 3, when we assign an object of Child class using pass by value to Base class object, it simply copies the object c after slicing all its Child class data members to b1 using an concept called object slicing which slices of the Child class object data members and copies only the parent data members to b1 so b1 will have the data members of Base class only(we can also say it completely a base class object )and all the subclass or Child class members has been sliced off. So when we call print function on b1 object it calls Base::print() as it only contains one print function. And there is no runtime polymorphism in this case because to perform polymorphism there should be child class function with same name. While in case 4, b2 is a pointer to base class and contains the address of object of Child class so when we call print() on b2 object, runtime polymorphism takes place which decides dynamically which function to call, as the Base class print function is made virtual so runtime polymorphism chooses Child::print() not Base::print().
Explanation:
Run time polymorphism is achieved only through the pointer (or reference) of base class type. Late binding(Runtime) is done in accordance with the content of pointer (i.e. location pointed to by pointer) and an Early binding(Compile time) is done according to the type of pointer, since print() function is declared with virtual keyword so it will be binded at run-time (output is print derived class as pointer is pointing to object of derived class ) and print() in first example is non-virtual so it will be binded during compile time.
Rules for defining Virtual Function:
- They Must be declared in public section of class.
- Virtual functions cannot be static and also cannot be a friend function of another class.
- Virtual functions should be accessed using pointer or reference of base class type to achieve run time polymorphism.
- The prototype of virtual functions should be same in base as well as derived class.
- They are always defined in base class and overridden in derived class. It is not mandatory for derived class to override (or re-define the virtual function), in that case base class version of function is used.
- A class may have virtual destructor but it cannot have a virtual constructor.
Virtual Function in Java
In Java, virtual function concept is very simple as all the functions except static or private or final are virtual functions by default.
In Java, as already said above all the member functions are virtual by default so when we called b.print() in line #7 in Main class, Child::print() is called unlike to c++ case #3(pass by value based), here in java all the non primitive data type are reference based which is similar to the case 4 in virtual example in c++. So this java case is similar to case 4 in virtual function example in c++ above where Base object b is storing the reference of the object and also the child object c is storing the reference to the object as shown in the output.
So the question here is that can we have non virtual function?
The answer is that we can?t exactly attain the non virtual behaviour in java, although we can make the base class function as final or private or static so that Child class don?t override it but we also won?t be able to define a member in Child class in case of static or final and we can?t call the actual function using object b in case Base::print() is private. So, we can partially achieve the behaviour of non virtual function but not exactly.