/*
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
*/