With virtual functions and polymorphism, it becomes possible to design and implement systems that are more easily extensible. Programs can be written to process objects of types that may not exist when the program is under development.
Polymorphic programming with virtual functions can eliminate the need for switch logic. The programmer can use the virtual function mechanism to perform the equivalent logic automatically, thus avoiding the kinds of errors typically associated with switch logic.
Derived classes can provide their own implementations of a base-class virtual function if necessary, but if they do not, the base class's implementation is used.
If a virtual function is called by referencing a specific object by name and using the dot member-selection operator, the reference is resolved at compile time (this is called static binding); the virtual function that is called is the one defined for the class of that particular object.
In many situations it is useful to define abstract classes for which the programmer never intends to create objects. Because these are used only as base classes, we refer to them as abstract base classes. No objects of an abstract class may be instantiated.
Classes from which objects can be instantiated are called concrete classes.
A class is made abstract by declaring one or more of its virtual functions to be pure. A pure virtual function is one with a pure specifier (= 0) in its declaration.
If a class is derived from a class with a pure virtual function and that derived class does not supply a definition for that pure virtual function, then that virtual function remains pure in the derived class. Consequently, the derived class is also an abstract class.
C++ enables polymorphismthe ability for objects of different classes related by inheritance to respond differently to the same member-function call.
Polymorphism is implemented via virtual functions and dynamic binding.
When a request is made through a base-class pointer or reference to use a virtual function, C++ chooses the correct overridden function in the appropriate derived class associated with the object.
Through the use of virtual functions and polymorphism, a member-function call can cause different actions, depending on the type of the object receiving the call.
Although we cannot instantiate objects of abstract base classes, we can declare pointers and references to objects of abstract base classes. Such pointers and references can be used to enable polymorphic manipulations of derived-class objects instantiated from concrete derived classes.
Dynamic binding requires that at runtime, the call to a virtual member function be routed to the virtual function version appropriate for the class. A virtual function table called the vtable is implemented as an array containing function pointers. Each class with virtual functions has a vtable. For each virtual function in the class, the vtable has an entry containing a function pointer to the version of the virtual function to use for an object of that class. The virtual function to use for a particular class could be the function defined in that class, or it could be a function inherited either directly or indirectly from a base class higher in the hierarchy.
When a base class provides a virtual member function, derived classes can override the virtual function, but they do not have to override it. Thus, a derived class can use a base class's version of a virtual function.
Each object of a class with virtual functions contains a pointer to the vtable for that class. When a function call is made from a base-class pointer to a derived-class object, the appropriate function pointer in the vtable is obtained and dereferenced to complete the call at execution time. This vtable lookup and pointer dereferencing require nominal runtime overhead.
Any class that has one or more 0 pointers in its vtable is an abstract class. Classes without any 0 vtable pointers are concrete classes.
New kinds of classes are regularly added to systems. New classes are accommodated by dynamic binding (also called late binding). The type of an object need not be known at compile time for a virtual-function call to be compiled. At runtime, the appropriate member function will be called for the object to which the pointer points.
Operator dynamic_cast checks the type of the object to which the pointer points, then determines whether this type has an is-a relationship with the type to which the pointer is being converted. If there is an is-a relationship, dynamic_cast returns the object's address. If not, dynamic_cast returns 0.
Operator typeid returns a reference to an object of class type_info that contains information about the type of its operand, including the name of the type. To use typeid, the program must include header file <typeinfo>.
When invoked, type_info member function name returns a pointer-based string that contains the name of the type that the type_info object represents.
Operators dynamic_cast and typeid are part of C++'s run-time type information (RTTI) feature, which allows a program to determine an object's type at runtime.
Declare the base-class destructor virtual if the class contains virtual functions. This makes all derived-class destructors virtual, even though they do not have the same name as the base-class destructor. If an object in the hierarchy is destroyed explicitly by applying the delete operator to a base-class pointer to a derived-class object, the destructor for the appropriate class is called. After a derived-class destructor runs, the destructors for all of that class's base classes run all the way up the hierarchythe root class's destructor runs last.