general arrays reuse-inheritance question

D

danra

Hi,

I have a question which seems to me pretty basic, unfortunately I
can't seem to figure it out.

Let's say I have an abstract base class Vehicle and classes Car and
Truck which derive from it.

Let's say I have abstract base class A which contains a list of
vehicles, and I define a method to insert and handle a vehicle into
the list.

Then I want to define class B which contains a list of cars, and I
want to reuse A's method for handling a new vehicle.

Here's the code:

class A
{
public:
A();
virtual ~A() = 0;

protected:
//appends vehicle to m_vehicleList
virtual void InsertVehicle(Vehicle* vehicle);

Vehicle* m_vehicleList;
}

class B : public A
{
public:
B();
virtual ~B();

//appends car to m_vehicleList
virtual void InsertCar(Car* car);
}

B::InsertCar obviously makes use of A::InsertVehicle, which inserts
the car into m_vehicleList.
The problem is, B has a list of vehicles instead of a list of cars,
which would present a problem the moment I wanted to write a method
which makes use of the "Car-ness" of the cars in the list.

A possible solution seems dropping m_vehicleList and adding a
parameter to InsertVehicle:

class A
{
public:
A();
virtual ~A() = 0;

protected:
//appends vehicle to vehicleList
virtual void InsertVehicle(Vehicle* vehicle, Vehicle**
vehicleList);
}

class B : public A
{
public:
B();
virtual ~B();

//appends car to m_carList
virtual void InsertCar(Car* car);

protected:
Car* m_carList;
}

And in InsertCat invoke InsertVehicle(car,&m_carList). Unfortunately
this wouldn't work, and rightly so, since "a parking lot of cars
is-not-a parking lot of vehicles".

So the question is - how can I reuse code so I won't have to write a
seperate InsertCar, InsertTruck etc. for every derived class of A?

Thank you very much.
 
S

Shezan Baig

danra said:
Hi,

I have a question which seems to me pretty basic, unfortunately I
can't seem to figure it out.

Let's say I have an abstract base class Vehicle and classes Car and
Truck which derive from it.

Let's say I have abstract base class A which contains a list of
vehicles, and I define a method to insert and handle a vehicle into
the list.

Then I want to define class B which contains a list of cars, and I
want to reuse A's method for handling a new vehicle.

Here's the code:

class A
{
public:
A();
virtual ~A() = 0;

protected:
//appends vehicle to m_vehicleList
virtual void InsertVehicle(Vehicle* vehicle);

Vehicle* m_vehicleList;
}

class B : public A
{
public:
B();
virtual ~B();

//appends car to m_vehicleList
virtual void InsertCar(Car* car);
}

B::InsertCar obviously makes use of A::InsertVehicle, which inserts
the car into m_vehicleList.
The problem is, B has a list of vehicles instead of a list of cars,
which would present a problem the moment I wanted to write a method
which makes use of the "Car-ness" of the cars in the list.

A possible solution seems dropping m_vehicleList and adding a
parameter to InsertVehicle:

class A
{
public:
A();
virtual ~A() = 0;

protected:
//appends vehicle to vehicleList
virtual void InsertVehicle(Vehicle* vehicle, Vehicle**
vehicleList);
}

class B : public A
{
public:
B();
virtual ~B();

//appends car to m_carList
virtual void InsertCar(Car* car);

protected:
Car* m_carList;
}

And in InsertCat invoke InsertVehicle(car,&m_carList). Unfortunately
this wouldn't work, and rightly so, since "a parking lot of cars
is-not-a parking lot of vehicles".

So the question is - how can I reuse code so I won't have to write a
seperate InsertCar, InsertTruck etc. for every derived class of A?

Thank you very much.

The original InsertVehicles() seemed *much* cleaner to me. And it is
probably the way to go. The only change I would make is to use a
vector of pointers instead of just a pointer. There is nothing wrong
with having a vector of pointers to base classes.

.. std::vector<Vehicle*> m_vehicleList;

What you want to do with this vector is another thing. Do you want to
perform some operations just on cars? Think about how you would do it
in a real parking lot. You would go to each vehicle, check if it a
car. If so, then do something with that car. You can do this in C++
as well:

.. for (m_vehicleList::iterator it = m_vehicleList.begin();
.. it != m_vehicleList.end(); ++it) {
.. // Check if it is a car
.. Car *pCar = dynamic_cast<Car*>(*it);
.. if (pCar) {
.. pCar->doSomething();
.. }
.. }

Hope this helps,
-shez-
 
N

Nicolas Pavlidis

[...]
The original InsertVehicles() seemed *much* cleaner to me. And it is
probably the way to go. The only change I would make is to use a
vector of pointers instead of just a pointer. There is nothing wrong
with having a vector of pointers to base classes.

. std::vector<Vehicle*> m_vehicleList;

I'd use here boost::shared_ptr:

std::vector<boost::shared_ptr<Vehicle> > m_vehicleList;

So noone have to worry about destoying the pointers stored by
std::vector correctly.

Kind regards,
Nicolas
 
S

Shezan Baig

Nicolas said:
[...]
The original InsertVehicles() seemed *much* cleaner to me. And it is
probably the way to go. The only change I would make is to use a
vector of pointers instead of just a pointer. There is nothing wrong
with having a vector of pointers to base classes.

. std::vector<Vehicle*> m_vehicleList;

I'd use here boost::shared_ptr:

std::vector<boost::shared_ptr<Vehicle> > m_vehicleList;

So noone have to worry about destoying the pointers stored by
std::vector correctly.

But should a parking lot destroy cars? :)
Depends who owns them, I guess.

-shez-
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top