CS115 Lab: C++ Virtual Functions

Highlights of this lab:

In this lab,  you will:

Lab Exercise:


Virtual Functions and Polymorphism.

Before getting into the details of virtual functions, let's have a look at why you need such things at all!!

In C++ The Complete Reference, Schildt says that a class that contains a virtual function is called a polymorphic class. This begs the question "What is polymorphism?". Schildt gives a very nice example of this term. He says to consider a house with an ordinary thermostat to control temperature. You know the house has a furnace but you don't know what kind. If you want to set the temperature you simply set the thermostat to the desired temperature. You don't know (or likely really care at all) how the furnace accomplishes its task. It might be a gas furnace, an electric heater, solar power - you don't care. You leave it up to the furnace to do its own task in a manner appropriate to that device.

How does this relate to polymorphism? Well, an analogy to computer programming is the concept of push/pop operations on various kinds of stacks.

The idea behind all this is to simplify the life of the operator - the programmer.

Declaring a Virtual Function in C++.

A virtual function is declared in a base class of a program and can then be redefined in each derived class. The declaration in the base class acts as a kind of template which can be enhanced by each derived class.

Here is a simple example.

#include <iostream>
using namespace std;

/*-------------------------------------------------
  Class Name:	base_class
-------------------------------------------------*/
class base_class {

		// The keyword VIRTUAL must be used here!!
public:		
   virtual void printit() {
       cout << "Print from base class\n";
       } 
}; // end base_class


/*-------------------------------------------------
  Class Name:	first_class
-------------------------------------------------*/
class first_class : public base_class  {
public:
    void printit() {
	cout << "Print from first class\n";
	} 
}; // end first_class


/**************************************************
   Name:	main 
**************************************************/
void main() {

base_class base;	// declare an object of the base class

base.printit();	// execute its virtual function

first_class first1;	// declare an object of the derived class

first1.printit();	// execute its virtual function

} // end main function

This is what you would see if you ran that program:
	Print from base class

	Print from first class

A few notes about virtual functions:

Virtual Functions and Inheritance

#include <iostream>
     using namespace std;

     /*-------------------------------------------------
       Class Name:   base_class
     -------------------------------------------------*/
     class base_class {

                     // The keyword VIRTUAL must be used here!!
     public:
        virtual void printit() {
             cout << endl << "Print from base class" << endl;
            }
     }; // end base_class


     /*-------------------------------------------------
       Class Name:   first_class
     -------------------------------------------------*/
     class first_class : public base_class  {
     public:
         void printit() {
             cout << endl << "Print from first class" << endl;
             }
     }; // end first_class

     /*-------------------------------------------------
       Class Name:   second_class
     -------------------------------------------------*/
     class second_class : public base_class  {
     }; // end second_class

     /*-------------------------------------------------
       Class Name:   coach_class
     -------------------------------------------------*/
     class coach_class : public base_class  {
     public:
         void printit() {
             cout << endl << "Print from coach class" << endl;
             }
     }; // end coach_class

     /*-------------------------------------------------
       Class Name:   tourist_class
     -------------------------------------------------*/
     class tourist_class : public coach_class  {
     }; // end tourist_class





/**************************************************
     Name:        main
**************************************************/
void main() {

     base_class base;        // declare an object of the base class
     base.printit();    // execute its virtual function

     first_class first1;     // declare an object of the derived class
     first1.printit();    // execute its virtual function

     second_class second1;     // declare an object for second
     second1.printit();

     coach_class coach1;     // declare an object for coach
     coach1.printit();

     tourist_class tour1;     // declare an object for tourist
     tour1.printit();

} // end main function

Here is what happens when that program is run:

mercury[20]% ex2

Print from base class

Print from first class

Print from base class

Print from coach class

Print from coach class
mercury[21]%
Examine the program and the output carefully to understand how it works.
Line PrintedSource of printing
Print from base class This is the base class virtual function.
Print from first class This is the first class virtual function.
Print from base class This is the second class virtual function.
But since there is no virtual function defined in "second class", the definition in the predecessor function is used. i.e. The base function.
Print from coach class This is the coach class virtual function.
Print from coach class This is the tourist class virtual function.
But since there is no virtual function defined in "tourist class", the definition in the predecessor function is used. In this case, the predecessor class is not "base" class, but "coach" class.

If you would like to experiment with that program you can copy it from the CS FTP Server. There are some comments in the program suggesting how you might modify the classes. To copy the program use the Hercules command-line ftp program from the CS FTP Server.

The path:	pub/class/170/ftp/cpp/Vfuncs

The file:      ex2-noptrs.cpp

Pure Virtual Functions

As you've seen in the previous example, if a derived class does not override a virtual function, it is the function definition in a predecessor class that is used. If the immediate predecessor has not overriden its predecessor, then the one before that is referenced to find a function definition. This search could continue (if predecessors don't override the virtual function) until, ultimately, it is the function definition in the base class that is used.

However, in some cases, it does not make sense for the base class to define the virtual function at all. The actual method should really be implemented in each one of the descendent classes. The base function should simply provide a kind of placeholder for the virtual function and leave it up to the descendents to specify the individual methods.

A virtual function that is declared but not defined in a base class is referred to as a pure virtual function. Here is the general syntax for declaring a pure virtual function:

virtual type function_name(parameter_list)=0;
Now when the base class uses a PURE virtual function, each descendent must override that function, or you will get a compile error. This makes sense, because the function has to be defined somewhere.

Here's another definition for you:
If a class contains a pure virtual function, that class is called an abstract class.
Because there is no definition for the function, you cannot create an object of that class. You can however, declare pointers to it.

Think of an abstract class as a general class that lays the foundation for descendent classes that define their own methods. This is the heart of polymorphism - let each class define its own operation.

The lab exercise in the next section illustrates these concepts. Study the C++ program for the exercise carefully, and be sure to read the comments.


Lab Exercise:


CS Dept Home Page
CS Dept Class Files
CS115 Lab Files

Copyright: Department of Computer Science, University of Regina.