Michael said:
Hi,
typedef std::vector<Vehicle*> VehicleList;
Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
Which one is better and why? If you could explain it by laying out some
codes, it would be highly appreciated!
Thanks in advance,
Michael
Because a Vehicle is abstract. Your goal here is to create a container
that holds derivatives of the Vehicle class. A Car is a type of
vehicle. A Truck is a type of Vehicle. A Bus is a type of Vehicle. Why
have to create a new container for each new type when a container of
Vehicles can store any type that is related to Vehicles, including a
mix of Vehicles?
Polymorphicly, you are creating a container of pointers to Vehicle
derivatives. That pointer to each element then allows the appropriate
behaviour to happen: brake(), reverse(), accelerate(). For example, a
car will not reverse() like a truck - a truck needs to sound a warning
buzzer first. The pointer essentially lets the vtable do its "magic".
As far as code is concerned:
#include <iostream>
#include <ostream>
#include <vector>
class Vehicle
{
public:
Vehicle() { }
virtual ~Vehicle() { } // virtual
virtual void reverse() = 0; // pure virtual -- see below
};
class Car : public Vehicle
{
public:
Car() { }
~Car() { std::cout << "~Car()" << std::endl; }
void reverse() { std::cout << "reversing" << std::endl; }
};
class Truck : public Vehicle
{
public:
Truck() { }
~Truck() { std::cout << "~Truck()" << std::endl; }
void reverse() { std::cout << "buzzer, reversing" << std::endl; }
};
int main()
{
std::vector< Vehicle* > vehicles;
// vehicles.push_back( new Vehicle ); error - Vehicle is abstract
vehicles.push_back( new Car );
vehicles.push_back( new Truck );
vehicles[ 0 ]->reverse();
vehicles[ 1 ]->reverse();
for ( int i = 0; i < vehicles.size(); ++i ) // or size_t
{
delete vehicles[ i ];
}
return 0;
}
/*
reversing
buzzer, reversing
~Car()
~Truck()
*/
The destructors are virtual too, they have to be for this to work. The
reason that reverse() was declared pure virtual in Vehicle is to force
the client programmer to provide a reverse() member function in order
to use this system.
Note that i can write a SportsCar class which derives from Car and
still use it in the vehicles container. A SportsCar is_a Car which is_a
Vehicle, hence a SportsCar is_a Vehicle.
If you don't yet see the benefits of such a system, consider
encapsulating the std::vector in a container class: all of a sudden,
you'ld have a container that can hold any Vehicle - including those
derivatives that have not been created yet (ie: SuperSportsCar or
TenTonTruck). Without having to modify the container in any way.
Thats a very powerful concept - your code becomes extensible without
having to modify the original classes.