简体   繁体   中英

C++ accesing pointer elements of a vector with iterator

with the code displayed below i have created 4 classes(3 subclasses and one superclass), each of them having the same print_info() function. I have created pointer objects from each class and inserted them into a vector created with the superclass.

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

using namespace std;

class Vehicle
{
    private:
        int wheels, max_speed;
        string model;
    public:
        virtual void print_info()
        {
             cout << "This is function print_info() in Vehicle (parent class)" << endl; 
        }
};

class Car: public Vehicle
{
    private:
        int doors, passengers;
    public:
        void print_info()
        {
             cout << "This is function print_info() in Car (child class)" << endl;
        }
};

class Bike: public Vehicle
{
    private:
        string owner;
        bool hasLights;
    public:
        string my_owner();
};

class Truck: public Vehicle
{
    private:
        float cargo_weight;
        int allowed_speed;
    public:
        void print_info()
        {
            cout << "This is function print_info() in Truck (child class)" << endl;
        }
};

int main()
{
    Vehicle *v1 = new Vehicle();
    Vehicle v2;
    Car c1;
    Car c2;
    Bike b1;
    Truck t1;
    Truck t2;

    vector <Vehicle> vvec;
    Vehicle *v = new Vehicle();
    Car *c = new Car();
    Bike *b = new Bike();
    Truck *t = new Truck();
    vvec.push_back(*v);
    vvec.push_back(*c);
    vvec.push_back(*b);
    vvec.push_back(*t);

    vector<Vehicle>::iterator iter = vvec.begin();
    while( iter != vvec.end()) 
    {
        iter->print_info();
        iter++;
    }

    v1 = &v2;
    v1->print_info();
    v1 = &c2;
    v1->print_info();
    v1 = &t2;
    v1->print_info();
    system("pause");

    return 0;
}

The wanted output is this:

This is function print_info in Vehicle (parent class)

This is function print_info in Car (child class)

This is function print_info in Vehicle (parent class)

This is function print_info in Truck (child class)

This is function print_info in Vehicle (parent class)

This is function print_info in Car (child class)

This is function print_info in Truck (child class)

Instead i am getting:

This is function print_info in Vehicle (parent class)

This is function print_info in Vehicle (parent class)

This is function print_info in Vehicle (parent class)

This is function print_info in Vehicle (parent class)

This is function print_info in Vehicle (parent class)

This is function print_info in Car (child class)

This is function print_info in Truck (child class)

I believe this is due to early binding but i don't know how to solve this!

You need to create vector of pointers vector <Vehicle*> vvec; , when you push_back like vvec.push_back(*v); you pass elements by value and it casts to Vehicle , so there won't be polymorphism because all elements of vector are just simple Vehicle objects, change to this:

//...
vector <Vehicle*> vvec;

Vehicle *v = new Vehicle();
Car *c = new Car();
Bike *b = new Bike();
Truck *t = new Truck();
vvec.push_back(v);
vvec.push_back(c);
vvec.push_back(b);
vvec.push_back(t);

vector<Vehicle*>::iterator iter = vvec.begin();
while( iter != vvec.end())
{
    (*iter)->print_info();
    iter++;
}
//...

And your output will be:

This is function print_info() in Vehicle (parent class)
This is function print_info() in Car (child class)
This is function print_info() in Vehicle (parent class)
This is function print_info() in Truck (child class)
This is function print_info() in Vehicle (parent class)
This is function print_info() in Car (child class)
This is function print_info() in Truck (child class)

This is a classic example of object slicing .

When you dereference the pointer to insert it to the vector vvec.push_back(*v) , you convert it to the base class type. Therefore, it now behaves as a 'Vehicle'.

If you want to get the behavior you expected, try using vector <Vehicle*> vvec and vvec.push_back(v) .

What you want is polymorphism, so you have to either store Vehicle references or a Vehicle pointers. And, since you cannot store references in a vector , pointer is the way to go.

vector <Vehicle*> vvec;

Then simply push the pointers and calling print_info will trigger polymorphic behaviors

    vvec.push_back(v);
    vvec.push_back(c);
    vvec.push_back(b);
    vvec.push_back(t);

    vector<Vehicle*>::iterator iter = vvec.begin();
    while( iter != vvec.end())
    {
        (*iter)->print_info();
        iter++;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM