0

Here's a sample program for what I'm talking about:

#include <iostream>
#include <list>

using namespace std;

class Thing {
    public:
        virtual void jump() { cout << "Called from Thing class" << endl; }
};

class Car: public Thing {
    public:
        virtual void jump() { cout << "Vroom vroom; imma car biotch" << endl; }
};

int main(int argc, char* argv[]) {

    Car myCar;

    list<Thing> myList;

    myList.push_back(myCar);

    std::list<Thing>::iterator iterator;
    for (iterator = myList.begin(); iterator != myList.end(); ++iterator) {
        iterator->jump();
    }

    return 0;
}

Output:

Called from Thing class

What I want to do is make a list of "Things". I want to be able to add instances of the child class from the Thing class; then I want to be able to call their overwritten function from an iterator.

The only issue is, even while using the "virtual" keyword, the iterator uses the Thing::jump function as opposed to the Car::jump function.

What can I do to make it not only work with Car, but all potential child classes from Thing, Car, etc. that overwrite the "jump" function?

Alex
  • 9,891
  • 11
  • 53
  • 87
Griffort
  • 1,174
  • 1
  • 10
  • 26

1 Answers1

0

In C++ values are what they say they are. You have a list of Thing not a list of Thing or derived types.

When you insert something into the list, a copy of it is created. In the case of inserting a derived type instance, this copies the Thing portion of the object, something known as object slicing (the Thing portion is sliced off).

There are a number of ways to store polymorphic data, but an instance of the base type is not one of them.

You could store std::unique_ptr<Base> in your list, for example. If you do so, ensure your base type has a virtual destructor to avoid undefined behaviour when theynare deleted by the default deleter.

#include <iostream>
#include <list>
#include <memory>

class Thing {
public:
  virtual void jump() { std::cout << "Called from Thing class\n"; }
  ~Thing(){}
};

class Car: public Thing {
public:
  virtual void jump() { std::cout << "Vroom vroom; I am a car\n"; }
};

then in main:

std::list<std::unique_ptr<Thing>> myList;

myList.push_back(std::make_unique<Car>());

for(auto&& ptr:myList){
    ptr->jump();
}
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524