Th C++ Pointer Rule

The rule as given in C++ terms is as follows. A pointer declared as pointing to a base class can be used to point to an object of a derived class of that base class, but a pointer to a derived class cannot be used to point to an object of the base class or to any of the other derived classes of the base class. In our program therefore, we are allowed to declare a pointer to the vehicle class which is the base class, and use that pointer to refer to objects of either the base class or any of the derived classes.

This is exactly what we do in the main program. We declare a single pointer which points to the vehicle class and use it to point to objects of each of the classes in the same order as in the last four programs. In each case, we allocate the object, send a message to the method named message() and deallocate the object before going on to the next class. You will notice that when we send the four messages, we are sending the message to the same method, namely the method named message() which is a part of the vehicle base class. This is because the pointer has a class associated with it. Even though the pointer is actually pointing to four different classes in this program, the program acts as if the pointer is always pointing to an object of the parent class because the pointer is of the type of the parent class.

The next program will finally do something you have not seen in any C program or in any C++ program in this tutorial up to this point. After you compile and execute the current program, we will go on to study our first virtual function.

An Actual Virtual Function

We finally come to an example program with a virtual function that operates as a virtual function and exhibits dynamic binding or polymorphism as it is called. This is in the program named VIRTUAL6.CPP.

This program is identical to the last example program except that the keyword virtual is added to line 8 to make the method named message() a virtual function. You will notice that the keyword virtual only appears in the base class, all classes that derive this class will have the corresponding method automatically declared virtual by the system. In this program, we will once again use the single pointer to the base class and allocate, use, then delete an object of each of the four available classes using the identical code we used in the last program. However, because of the addition of the keyword virtual in line 8, this program acts entirely different from the last example program.

Since the method named message() is declared to be a virtual method in its declaration in the base class, anytime we refer to this method with a pointer to the base class, we actually execute the method associated with one of the derived classes if there is a method available in the derived class and if the pointer is actually pointing to that derived class. When the program is executed, the output reflects the same output we saw in the other cases when we were actually calling the methods in the derived classes, but now we are using a pointer of the base class type to make the calls.

You will notice that in lines 40, 44, 48, and 52, even though the code is identical in each line, the system is making the decision of which method to actually call based on the type of the pointer when each message is sent. The decision of which method to call is not made during the time when the code is compiled but when the code is executed. This is dynamic binding and can be very useful in some programming situations. In fact, there are only three different calls made because the class named truck does not have a method named message(), so the system simply uses the method from the base class to satisfy the message passed. For this reason, a virtual function must have an implementation available in the base class which will be used if there is not one available in one or more of the derived classes. Note that the message is actually sent to a pointer to the object, but this is splitting hairs and should not be overly emphasized at this time.

It is probably not obvious but the observant student will note that the structure of the virtual function in the base class and each of the derived classes is identical. The return type and the number and types of the parameters must be identical for all since a single statement can be used to call any of them.

Is this Really Significant?

This program probably does not seem to do much when you first approach it, but the dynamic binding is a very useful construct and will be illustrated in the next chapter with a rather simple program that uses the technique of dynamic binding to implement a personnel list for a small company.

If the keyword virtual is used, the system will use late binding which is done at run time, but if the keyword is not included, early binding will be used. What these words actually mean is that with late binding, the compiler does not know which method will actually respond to the message because the type of the pointer is not known at compile time. With early binding, however, the compiler decides at compile time what method will respond to the message sent to the pointer.

Be sure to compile and execute this example program before continuing on to the next chapter where we will see a practical example of the use of this technique.