/* The inheritance hierarcy in this program is sound. Both Car and Truck are specialization of the base class Vehicle. Class Garage manages cars and truck uniformly with respect to the base class interface. The public inheritance establishes valid "is a kind of" relationships between the base class and the derived classes. Other part of the program can deal with Car and Truck objects knowing only that they are at least Vehicle objects and they react to the interface established by the public members of Vehicle. Although the inheritance is valid, the detailed distribution of code between the base and derived classes can be improved. To make a better version from the example, try to answer the following questions: - What is common among classes of an inheritance hierarcy - What are the differences between the derived classes The common properties of all vehicles are a license plate number and the ability to identify themselves. These properties are captured in the plate base class data member, and virtual member fuction identify(). Vhat is the difference between a Car and a Truck? The only difference is the string "car" or "truck" printed by identify(). In other words, truck and car differ only in value not in their behaviour. The similarity between Car::identify() and Truck::identify() is telling. In the following, we migrate common behaviour - represented by the identify() function - to the base class. */ #include <stdio.h> #include <string.h> class Vehicle { public: Vehicle() { plate = 0; } Vehicle(char *p) { plate = new char[strlen(p)+1]; strcpy(plate, p); } virtual ~Vehicle() { delete [] plate; } void identify() { char *p = plate ? plate : "none"; printf( "%s with plate %s\n", group(), p); } protected: virtual char *group() = 0; private: char *plate; }; /* The virtual behaviour identify() has been replaced by the virtual behaviour of group(). In fact, group() itselfmay be replaced with a data member. Plate member has been moved from the protected area to private. Car and Vehicle has been also modified accordingly to the changes at Vehicle. */ class Car : public Vehicle { public: Car() : Vehicle() { } Car(char *p) : Vehicle(p) { }; private: char *group() { return "car"; } }; class Truck : public Vehicle { public: Truck() : Vehicle() { } Truck(char *p) : Vehicle(p) { }; private: char *group() { return "truck"; } }; class Garage { public: Garage(int max); ~Garage(); int accept(Vehicle*); Vehicle *release(int bay); void listVehicles(); private: int maxVehicles; Vehicle **parked; }; Garage::Garage(int max) { maxVehicles = max; parked = new Vehicle*[maxVehicles]; for( int bay = 0; bay < maxVehicles; ++bay ) { parked[bay] = 0; } } Garage::~Garage() { delete [] parked; } int Garage::accept(Vehicle *veh) { for( int bay = 0; bay < maxVehicles; ++bay ) if( !parked[bay] ) { parked[bay] = veh; return( bay ); } return( -1 ); // No free bay } Vehicle *Garage::release(int bay) { if( bay < 0 || bay > maxVehicles ) return 0; Vehicle *veh = parked[bay]; parked[bay] = 0; return( veh ); } void Garage::listVehicles() { for( int bay = 0; bay < maxVehicles; ++bay ) if( parked[bay] ) { printf("Vehicle in bay %d is: ", bay); parked[bay]->identify(); } } Car c1("AAA100"); Car c2("BBB200"); Car c3("CCC300"); Truck t1("TTT999"); Truck t2("SSS888"); Truck t3("UUU777"); int main( ) { Garage Park(14); Park.accept(&c1); int t2bay = Park.accept(&t2); Park.accept(&c3); Park.accept(&t2); Park.release(t2bay); Park.listVehicles(); return 0; } /* The output of the program is the following: Vehicle in bay 0 is: car with plate AAA100 Vehicle in bay 2 is: car with plate CCC300 Vehicle in bay 3 is: truck with plate SSS888 */