vector of different subclasses

I have a class Automobile, looks like this

class Automobile{
public:
Automobile();
void accelerate();
void break();
};

I also have classes

class Car : Automobile{};
class Truck : Automobile{};
class Motorcycle : Automobile{};

Cars, Trucks, and Motorcycles accelerate and brake at different rates, but generally behave the same.

What I would like to do is have a vector

vector <Automobile> automobiles;

and assign classes to vector as such:

Car honda;
Truck ford;
Motorcycle kawasaki;

automobiles[] = honda;
automobiles[] = ford;
automobiles[] = kawasaki;

and be able to call the parent class (Automobile) functions:

automobiles[0].accelerate();
automobiles[1].brake();

etc.

I've recently introduced myself to templates looking for a solution to this, but that doesnt seem to be applicable to what I need to do... I've searched everywhere but I'm probably using the wrong key words or something :)

thanks for any and all help :)
You need polymorphism for this.

Container (vector) should hold pointers to objects:
std::vector<Automobile *>

You can use some kind of smart pointer class instead of standard pointers to simplify handling of objects (creation and destruction).

EDIT: Actually, in the example above, you don't need polymorphism since you want to call methods of a base class, and you allocate objects on the stack (no need for virtual destructors). So you can simply make a vector of pointers to a base class. I didn't delete my previous answer as your real code may be different.
Last edited on
Here's a similar example, using polymophism:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <vector>
using namespace std;

// abstract base class
class Animal
{
public:
    // pure virtual method
    virtual void speak() = 0;
    // virtual destructor
    virtual ~Animal() {}
};

// derived class
class Dog : public Animal
{
public:
    // polymorphic implementation of speak
    virtual void speak() { cout << "Ruff!"; }
};

int main( int argc, char* args[] )

    // container of base class pointers
    vector<Animal*> barn;

    // dynamically allocate an Animal instance and add it to the container
    barn.push_back( new Dog() );

    // invoke the speak method of the first Animal in the container
    barn.front()->speak();

    // free the allocated memory
    for( vector<Animal*>::iterator i = barn.begin(); i != barn.end(); ++i )
    {
        delete *i;
    }
    // empty the container
    barn.clear();

    return 0;
}


The reason for storing base class pointers is because the STL container will make its own copy of the object being inserted. If the container is of the base class, Automobile, it will only copy the base class portion of the object. If the container is of base class pointers, Automobile*, a pointer to the complete object will be stored.

The drawback (if you would call it that) to storing pointers is that memory management is now up to you. Using dynamically allocated memory will allow your container hold valid pointers, regardless of scope. For example, without dynamically allocating the object, the following issue exists:
1
2
3
4
5
6
7
//...
vector<Animal*> barn;
{
    Dog spike;                 // spike is a local variable
    barn.push_back( &spike );
}                              // from this point on, barn contains an invalid pointer
                               // because spike has gone out of scope 


A better solution for memory management would be a smart pointer, also recommended by Abramus. For example, see http://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/shared_ptr.htm

One last note on the polymorphism. In the example above, the virtual methods could be regular methods if you do not need a different derived behavior. From the original post, it read as if the data members will differ but the behavior will remain the same.

Hope this helps.
Last edited on
Thanks, exactly what I was looking for!
Topic archived. No new replies allowed.