home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 10
- VIRTUAL FUNCTIONS
-
- Once again we are into a completely new topic with terminology
- which will be new to you. If you are new to object oriented
- programming, you should follow along in this chapter very
- carefully because every attempt has been made to define every
- detail of this new and somewhat intimidating topic. However, if
- you are well versed in object oriented programming, simply
- learning to use C++, you may wish to skip the first four programs
- in this chapter and go directly to the example program named
- VIRTUAL5.CPP and continue from there to the end of the chapter.
-
- One term which must be defined is polymorphism, a rather large
- word that simply means similar when used in the context of object
- oriented programming. Objects are polymorphic if they have some
- similarities but are still somewhat different. We will see how
- it is used in the context of object oriented programming as we
- proceed through this chapter.
-
- We have already studied operator overloading and function
- overloading in this tutorial, and they are a subtle form of
- polymorphism since in both cases, a single entity is used to
- refer to two or more things. The use of virtual functions can be
- a great aid in programming some kinds of projects as you will see
- in these two chapters.
-
-
- A SIMPLE PROGRAM WITH INHERITANCE
- -----------------------------------------------------------------
- Examine the example program named ==================
- VIRTUAL1.CPP for the basic program outline VIRTUAL1.CPP
- we will use for all discussion in this ==================
- chapter. Since this program has nothing to
- do with virtual functions, the name may be somewhat misleading.
- It is named VIRTUAL1.CPP because it is part of a series of
- programs intended to illustrate the use of virtual functions. The
- last program in this chapter will illustrate the proper use of
- virtual functions. The first program is very simple and you will
- recognize it as being similar to the programs studied in the last
- chapter except that this program is greatly simplified in order
- to effectively instruct you in the use of a virtual function.
- You will notice that many of the methods from the last chapter
- have been completely dropped from this example for simplicity,
- and a new method has been added to the parent class, the method
- named message() in line 8. Throughout this chapter we will be
- studying the operation of the method named message() in the base
- class and the derived classes. For that reason, there is a
- method named message() in the car class as well as in the new
- class named boat in lines 27 through 32.
-
-
-
- Page 10-1
-
- Chapter 10 - Virtual Functions
-
- You will also notice that there is a lack of a method named
- message() in the truck class. This has been done on purpose to
- illustrate the use of the virtual method, or if you prefer, you
- can refer to it as a virtual function. You will recall that the
- method named message() from the base class is available in the
- truck class because the method from the base class is inherited
- with the keyword public included in line 19. You will also
- notice that the use of the keyword public in lines 12 and 27
- actually do nothing because the only method available in the base
- class is also available in the derived classes. There are no
- methods actually inherited. Leaving the keyword in the header
- poses no problem however, so it will be left there for your
- study.
-
- The method named message() in the base class and in the derived
- classes has been kept very simple on purpose. Once again, we are
- interested in the technique of the virtual method rather than a
- long complicated example.
-
- The main program is as simple as the classes, one object of each
- of the classes is declared in lines 37 through 40 and the method
- named message() is called once for each object. The result of
- executing the program indicates that the method for each is
- called except for the object named semi, which has no method
- named message(). As discussed in the last chapter, the method
- named message() from the parent class is called and the data
- output to the monitor indicates that this did happen since it
- displays "Vehicle message" for the object named semi.
-
- The data for the objects is of no concern in this chapter so all
- data is allowed to default to private type and none is inherited
- into the derived classes. Some of the data is left in the
- example program simply to make the classes look like classes.
- Based on your experience with C++ by now, you realize that the
- data could be removed since it is not used.
-
- After you understand this program, compile and execute it to see
- if your compiler gives the same result of execution.
-
-
- ADDING THE KEYWORD VIRTUAL
- -----------------------------------------------------------------
- As you examine the next example program ==================
- named VIRTUAL2.CPP, you will notice that VIRTUAL2.CPP
- there is one small change in line 8. The ==================
- keyword virtual has been added to the
- declaration of the method named message() in the parent class.
- It may be a bit of a disappointment to you to learn that this
- program operates no differently than the last example program.
- This is because we are using objects directly and virtual methods
- have nothing to do with objects, only with pointers to objects as
- we will see soon. There is an additional comment in line 46
- illustrating that since all four objects are of different
-
- Page 10-2
-
- Chapter 10 - Virtual Functions
-
- classes, it is impossible to assign any object to any other
- object in this program. We will soon see that some pointer
- assignments are permitted between objects of dissimilar classes.
-
- After you are sure that the fact that they are virtual functions,
- or methods, has nothing to do with the objects as they are
- instantiated, compile and execute this example program to see if
- your compiler results in the same output as that listed.
-
-
- USING OBJECT POINTERS
- -----------------------------------------------------------------
- Examine the example program named ==================
- VIRTUAL3.CPP and you will find a repeat of VIRTUAL3.CPP
- the first program but with a different main ==================
- program. In this program the keyword virtual
- has been removed from the method declaration in the parent class
- in line 8, and the main program declares pointers to the objects
- rather than declaring the objects themselves in lines 37 through
- 40. Since we only declared pointers to the objects we find it
- necessary to allocate the objects before using them by using the
- new operator in lines 42 through 49. Upon running the program,
- we find that even though we are using pointers to the objects we
- have done nothing different than what we did in the first
- program. Upon execution, we find that the program operates in
- exactly the same manner as the first example program in this
- chapter. This should not be surprising because a pointer to a
- method can be used to operate on an object in the same manner as
- an object can be manipulated.
-
- Be sure to compile and execute this program before continuing on
- to the next example program. The observant student will notice
- that we failed to deallocate the objects prior to terminating the
- program. As always, in such a simple program, it doesn't matter
- because the heap will be cleaned up automatically when we return
- to the operating system.
-
-
- A POINTER AND A VIRTUAL FUNCTION
- -----------------------------------------------------------------
- The example program named VIRTUAL4.CPP is ==================
- identical to the last program except for the VIRTUAL4.CPP
- addition of the keyword virtual to line 8 ==================
- once again. I hope you are not terribly
- disappointed to find that this program, including the keyword
- virtual, is still identical to the last program. Once again we
- are simply using pointers to each of the objects, and in every
- case the pointer is of the same type as the object to which it
- points. You will begin to see some changes in the next example
- program, so be patient, we are almost there.
-
- Once again, it would be best for you to compile and execute this
- program.
-
- Page 10-3
-
- Chapter 10 - Virtual Functions
-
- The four previous programs were meant to instruct you in what
- virtual functions do not do. The next two will show you what
- virtual functions do.
-
-
- A SINGLE POINTER TO THE PARENT CLASS
- -----------------------------------------------------------------
- Examine the example program named ==================
- VIRTUAL5.CPP where we almost use a virtual VIRTUAL5.CPP
- method. Be just a little patient because we ==================
- are almost ready to actually use a virtual
- method.
-
- You will notice that this is another copy of our program with the
- keyword virtual omitted from line 8 and with a totally different
- main program. In this program, we only declare a single pointer
- to a class and the pointer is pointing to the base class of the
- class hierarchy. We will use the single pointer to refer to each
- of the four classes and observe what the output of the method
- named message() is.
-
- A little digression is in order to understand how we can use a
- pointer which has been declared to point to one class, to
- actually refer to another class. If we referred to a vehicle (in
- the real world, not necessarily in this program), we could be
- referring to a car, a truck, a motorcycle, or any other kinds of
- transportation, because we are referring to a very general form
- of an object. If however, we were to refer to a car, we are
- excluding trucks, motorcycles, and all other kinds of
- transportation, because we are referring to a car specifically.
- The more general term of vehicle can therefore refer to many
- kinds of vehicles, but the more specific term of car can only
- refer to a single kind of vehicle, namely a car.
-
- We can apply the same thought process in C++ and say that if we
- have a pointer to a vehicle (remembering that a pointer is
- actually a reference), we can use that pointer to refer to any of
- the more specific objects, and that is indeed legal in C++
- according to the definition of the language. In a like manner,
- if we have a pointer to a car, we cannot use that pointer to
- reference any of the other classes including the vehicle class
- because the pointer to the car class is too specific and
- restricted to be used on any of the other classes.
-
-
- THE 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
-
- Page 10-4
-
- Chapter 10 - Virtual Functions
-
- vehicle class which is the base class, and use that pointer to
- refer to objects of 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 VIRTUAL6.CPP
- 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.
-
-
- Page 10-5
-
- Chapter 10 - Virtual Functions
-
- 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 one is not
- 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
- functions, 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.
-
-
- PROGRAMMING EXERCISES
- -----------------------------------------------------------------
- 1. Modify VIRTUAL3.CPP to deallocate the objects prior to
- terminating the program.
-
- 2. Add a message() method to the truck class of VIRTUAL6.CPP to
- observe the use of the new method instead of defaulting to
- the parent class method.
-
- Page 10-6
-