![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
[an error occurred while processing this directive]
introduce two new member functions for class Car. Neither of these two member functions is declared in Vehicle. You do, however, declare them virtual so that any derived class of Car can use the dynamic binding mechanism. The class declaration is finished with the declaration of two private data members named degrees and drivingLights. The degrees variable will maintain the state of degrees of steering and drivingLights will hold the state of the headlights (on or off). You should familiarize yourself with the implementation of the Car class found in the CAR.CPP file. I will not detail the functionality of the Car class here, but will concentrate on the functionality of the main function found in MAIN.CPP. Each of the first two statements in function main creates an instance of type Car as shown here: Vehicle *sporty = new Car() ; Car *luxury = new Car() ; Notice that the first statement declares sporty to be a pointer to a Vehicle object, whereas luxury is declared to be a pointer to a Car object. It is important to remember this as you move through the code. The new expression in each statement both creates an object of type Car and returns a pointer. The pointer returned to luxury is of type Car, but for sporty, the pointer returned is of type Vehicle. Look at the next two lines of code: sporty->setSpeed( 120 ) ; sporty->decelerate( 20 ) ; The first statement is a call to the member function setSpeed through the pointer sporty. Is the call made to the setSpeed member function defined in Vehicle or Car? You might think that because the pointer is of type Vehicle that Vehicles setSpeed function is called. However, in actuality, it is Cars setSpeed function that is invoked. Remember that the setSpeed member function is declared virtual in the base class. The rule is this: A function is invoked based on the type of the object, not the reference (or pointer) to the object. This behavior is confirmed with the output of sportys speed, which is 60. If setSpeed were called for the Vehicle class, the speed reported for sporty would be 100. Each of the next four lines of code that follow luxury->setSpeed( 35 ) ; luxury->steer( 20 ) ; luxury->headLights( Vehicle::SWITCH_ON ) ; luxury->accelerate( 15 ) ; calls the specified member function of the Car class, with the exception of accelerate. The member function accelerate is not redeclared for the Car class, so it is Vehicle::accelerate that is invoked. The two cout statements print out the speed value for each object. The if-else statement that follows reports whether the sporty object is moving. Finally, the delete expression is called for each dynamically allocated object. Comments The power of polymorphism offers you the opportunity to manipulate more than one derived type object with just a base class pointer (or reference). Because you can refer to a derived type object using a base class pointer, you can write programs without regard to the actual object. The following example should help to clarify the power of polymorphism. Suppose you create two new classes, SportsCar and StationWagon, both derived from Car. Obviously, an object of type SportsCar accelerates and decelerates differently than an object of type StationWagon. Without the use of polymorphism, a possible implementation would be as follows: //... if( typeid(StationWagon) == typeid(*pType) ) { StationWagon *p = (StationWagon *)pType ; p->steer( 14 ) ; p->accelerate( 5 ) ; } else if( typeid(SportsCar) == typeid(*pType) ) { SportsCar *p = (SportsCar *)pType ; p->steer( 25 ) ; p->accelerate( 20 ) ; } else if( typeid(Car) == typeid(*pType) ) { Car *p = (Car *)pType ; p->steer( 16 ) ; p->accelerate( 10 ) ; } The typeid operator is used to return a const reference to a type_info object. The argument to typeid is either a type name or expression. An expression can be a reference or pointer of some type. If the expression is a reference or pointer, the type_info reference reveals the actual type referred to, not the type of the reference (or pointer). You can use the operator== and operator!= member functions to determine the equality, or inequality, of two type_info objects. Consider what would be required if you added another type derived from Car to your hierarchy. You would have to visit all runtime type information (RTTI) logic, make appropriate enhancements, and recompile the whole affair. As the name suggests, RTTI is used to retrieve information about an object at runtime. The runtime identification mechanism is implemented with respect to polymorphic types. This implies that a class must contain at least one virtual function. The performance and readability penalty will also be high with all the if-elses to step through. Virtual functions are a more elegant solution to this type of runtime logic, as you have seen in this How-To. 3.5 Implement static members of a class?Problem I have heard that class members can be declared with the static keyword. I would like to know when to use a static member for a class and the syntax required for declaring one. Technique In this How-To, a program will be used to demonstrate the use of a static data member of a class. Static data members can be quite useful for certain programming situations. In this How-To, you will discover one such use with the program provided.
|
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.
|