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