Inheritance/Polymorphism  «Prev  Next»
Lesson 11 Virtual functions
Objective Virtual function selection

Add a virtual function to the Shape Class

A virtual function and its derived instances that have the same signature must have the same return type. The virtual function redefinition is called overriding. Notice that nonvirtual member functions with the same signature can have different return types in derived classes. The return type rule is undergoing reconsideration by the ANSI standards committee. Namely, many compilers require that virtual functions are overridden using the same return type. This restriction is relaxed where a derived class replaces the base class as the return type. C++ virtual function is a member function of a class, whose functionality can be over-ridden in its derived classes.
The whole function body can be replaced with a new implementation in the derived class.
  • C++ Virtual Function Properties C++ virtual function is,
    1. A member function of a class
    2. Declared with virtual keyword
    3. Usually has a different functionality in the derived class
    4. A function call is resolved at run-time

    The difference between a non-virtual c++ member function and a virtual member function is, the non-virtual member functions are resolved at compile time. This mechanism is called static binding. However, the c++ virtual member functions are resolved during run-time. This mechanism is known as dynamic binding.

Virtual Functions

When you specify a function as virtual in a base class[1], you indicate to the compiler that you want dynamic binding for function calls in any class that is derived from this base class. A virtual function is declared in a base class by using the keyword virtual, as shown in Figure 4-11
Figure 3-6: Types of Nested Classes.
Figure 4-11: Calling a virtual function

A function that you specify as virtual in a base class will be virtual in all classes that are directly or indirectly derived from the base. This is the case whether or not you specify the function as virtual in a derived class. To obtain polymorphic behavior, each derived class may implement its own version of the virtual function. You make virtual function calls using a variable whose type is a pointer or a reference to a base class object.
Figure 4-11 illustrates how a call to a virtual function through a pointer is resolved dynamically. The pointer to the base class type is used to store the address of an object with a type corresponding to one of the derived classes. It could point to an object of any of the three derived classes shown or, of course, to a base class object. The type of the object to which the pointer points when the call executes determines which volume() function is called. Describing a class as polymorphic means that it is a derived class that contains at least one virtual function. Note that a call to a virtual function using an object is always resolved statically. You only get dynamic resolution of calls to virtual functions through a pointer or a reference. Storing an object of a derived class type in a variable of a base type will result in the derived class object being sliced, so it has not derived class characteristics.
With that said, let us give virtual functions a whirl. To make the previous example work as it should, a very small change to the Box class is required. I just need to add the virtual keyword to the definition of the volume() function
class Box
{
// Rest of the class as before...
public:
// Function to calculate the volume of a Box object
virtual double volume() const { return length*width*height; }
};

Virtual function must be executable Code

An ordinary virtual function must be executable code. When invoked, its semantics are the same as those of other functions. In a derived class, it can be overridden, and the function prototype of the derived function must have matching signature and return type. This is in contrast to an overloaded member function, which is compile-time selected based on its signature. An overloaded member function can have distinct return types. The selection of which function definition to invoke for a virtual function is dynamic. The typical case occurs when a base class has a virtual function and derived classes have their versions of this function. A pointer to a base class can point at either a base class object or a derived class object. The member function selected will depend on the class of the object being pointed at, not on the pointer type.
In the absence of a derived type member, the base class virtual function is used by default. Also, once declared virtual, this property is carried along to all redefinitions in derived classes. It is unnecessary in the derived class to use the function modifier virtual.
Consider the following example:
//virtual function selection.
class B {
public:
   int  i;
   virtual void  print_i() const
     { cout << i << " inside B" << endl; }
};

class D : public B {
public:
   //virtual as well
   void  print_i() const
     { cout << i << " inside D" << endl; }
};

int main()
{
   B   b;
   B*  pb = &b;              //points at a B object
   D   f;
    
   f.i = 1 + (b.i = 1);
   pb -> print_i();          //call B::print_i()
   pb = &f;                  //points at a D object
   pb -> print_i();          //call D::print_i()
}

The output from this program is
1 inside B
2 inside D

Virtual Exercise - Exercise

Click the Exercise link to add a virtual function to the shape class that returns the name of a shape as a char* value.
Virtual Exercise - Exercise

[1]base class: A base class is an existing class from which the other classes are derived and inherit the methods and properties. A derived class is a class that is constructed from a base class or an existing class.

SEMrush Software