/* Value vesus behaviour Vehicle::identify() was a virtual function in the original version of the program, and following that style group() is virtual in the revised version. Is a virtual function is the right way to capture the difference between the characteristic strings "car" and "truck"? The difference between the derived classes is one of value and not behaviour. Objects ofthe derived classes do not behave differently nor use different algorithms. A difference in value can be recorded more naturally in a data member than in a virtual function. A data member in Vehicle would be sufficient: */ #include <stdio.h> #include <string.h> class Vehicle { public: // Vehicle(char *g) { group = g; plate = 0; } Vehicle(char *g, char *p) { group = g; plate = new char[strlen(p)+1]; strcpy(plate, p); } virtual ~Vehicle() = 0; // pure virtual void identify() { char *p = plate ? plate : "none"; printf( "%s with plate %s\n", group, p); } private: char *plate; char *group; }; /* The data member can receive its value from an additional argument to each Vehicle constructor, supplied by the corresponding derived constructor. The base and the derived classes interact only during initialization, further reducing coupling. */ Vehicle::~Vehicle() { delete [] plate; } class Car : public Vehicle { public: // Car() : Vehicle("car") { } Car(char *p = 0) : Vehicle("car", p) { }; }; class Truck : public Vehicle { public: // Truck() : Vehicle("truck") { } Truck(char *p = 0) : Vehicle("truck", p) { }; }; /* We can further reduce the code by using default argument in the constructors of the derived classes and so eliminating the second cosntructors both in derived and the base classes. In the same time we must mentioned that when we eliminated a virtual function we increased the size of the object. So the data versus function tradeoff has a size versus runtime parallel. Here we should recognize, that eliminating the virtual function also eliminated the v_ptr, se reduced size. */ 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 */