![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
To access the contents, click the chapter and section titles.
C++ in Plain English
Chapter 9
|
![]() | What does the virtual in virtual function mean, anyway? In computer termssuch as virtual memory and virtual realityvirtual usually describes something that isn't quite real but works as if it were. In the case of functions, virtual describes a function call that, at run time, could refer to any number of different function calls. It is not a real function call in that it doesn't correspond to a specific code address. In some ways, the name is misleading, because virtual functions are entirely real. They are simply called through indirect function calls rather than standard function calls. |
To make a member function into a virtual function, precede the function declaration with the virtual keyword. The keyword must appear at the beginning of the declaration, before the return-value type.
virtual return_type name(arguments);
As a result, the function is declared virtual, meaning that it is late bound. In late binding, the address of the function does not have to be determined until run time. (I devote most of the rest of the chapter to explaining when this is useful.)
Once the virtual keyword is used in the function declaration, you don't need to use it again either in the function definition, in derived class declarations, or in derived class function definitions. The function remains virtual in all derived-class declarations using the same name and type.
For example, suppose you have a class CTimePiece that has a ShowTime function. This function is declared virtual.
class CTimePiece { public: virtual void ShowTime(void); ... };
The function definition for ShowTime does not need to include the virtual keyword.
#include <iostream.h> void CTimePiece::ShowTime(void) { cout << hours << : << minutes; };
In any classes derived, directly or indirectly, from CTimePiece, the ShowTime function is virtualincluding the following class, which overrides the ShowTime function.
class CClock : public CTimePiece { public: void ShowTime(void); // Override function ... }; void CClock::ShowTime(void) { paint_clock_face(hours, minutes); }
There is no requirement that a virtual function be overridden by derived classes or that it be called through a pointer. A virtual function can be called in the same ways as any other member function is called. There is no difference in the syntax, either in declaration or in usage. (This is to say that the syntax in the C++ source code looks the same as for normal member functions, even though there are differences under the covers.)
CTimePiece time; CClock clock; time.ShowTime(); clock.ShowTime();
Virtual functions do have a few minor restrictions. Inline functions cannot be virtual, for example.
The effect of making a function virtual most often shows up when you access objects through base-class pointers. (You might want to review the last section in Chapter 8 Inheritance: C++ and Good Genes if you haven't read it.) With the ShowTime function, you could use the same line of code to call different function implementations. In the following example, assume that CClock and CDigital are both derived classes of CTimePiece.
CTimePiece *pTime; pTime = new CClock; pTime->ShowTime(); // Calls CClock::ShowTime pTime = new CDigital; pTime->ShowTime(); // Calls CDigital::ShowTime
As I mentioned in the previous section, there is no difference in syntax between virtual and nonvirtual functions except for the one-time use of virtual in a declaration. This is true even though C++ handles them differently. This fact makes it easy to introduce virtual functions into existing C++ projects.
But should you make all your functions virtual just because it's easy to do so? Except for inline functions, you could make almost all your functions virtual simply by putting the keyword everywhere the functions are first declared. But not all functions should be virtual functions.
If there's no chance that a function will ever be overridden by a derived class, then it should not be declared virtual. If you write a class that you never intend to derive other classes from, there is no point in making any function virtual. Every time you call a virtual function, you pay a slight performance penalty. Each virtual function also takes up slightly more space in program memory than its nonvirtual counterpart would. The point is that there's no reason to make a function virtual unless doing so might make a difference.
But if you write a function in a base class and it is clear that the function is intended to be overridden in derived classes, then it is wise to declare the function virtual. You can override a function in a derived class even though it is not virtual, but then in certain situations the wrong function might be called.
In the example at the end of the last chapter, the following code calls the function CStr::cpy (the base-class version) even though it looks as if it should call CPoStr::cpy (the derived-class version).
CIoStr prstr; CStr pStr = &prstr; pStr->cpy(Initialize me.);
But if the cpy function were originally declared as virtual, then this code would call CIoStr::cpy as expected.
class CStr { ... virtual void cpy(char *s); ...
Previous | Table of Contents | Next |
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement. |