I tried to add objects to the "content" vector, and use show() on all of them.
But the objects that are children (A, B) of "Base" behave like they were of "Base" type,
what is not my intention. As it seems, I tried to use virtual functions but it doesn't work.
I hope that the code will speak for itself.
class Base {
public:
virtual void show() { cout << "Base "; }
};
class A : public Base {
public:
virtual void show() { cout << "A "; }
};
class B : public Base {
public:
virtual void show() { cout << "B"; }
};
vector<Base> content;
void add(Base &o) {
content.push_back(o);
}
A test1;
B test2;
add(test1);
add(test2);
for (size_t i = 0; i < content.size(); i++) {
collection[i].show(); // output is: Base Base instead of A B
}
Thanks in advance.
vector<Base*> content; // <<
void add(Base *o) { // <<
content.push_back(o);
}
A test1;
B test2;
add(&test1); // <<
add(&test2); // <<
for (size_t i = 0; i < content.size(); i++) {
collection[i]->show(); // <<
}
What you have is a vector of Base.
When you add somthing to a vector it is copied into the vector But only the baser part is being copied. Thus you will loose all the dertived information.
This is cooqually refered to as the slicing problem.
A simple solution is to store pointers in the vector.
As others have said, you're experiencing slicing. The vector
stores a Base
, and any derived information gets sliced away.
Alleviate this with pointers:
std::vector<Base*> v;
v.push_back(new A);
v.push_back(new B);
The problem now is with releasing your resources. Before the vector goes out of scope, you'll need to iterate through it and delete each element. An even worse problem is with exceptions.
If at any point during the life-time of the vector, if an exception is thrown, it will unwind the stack, at some point releasing all your pointers in the vector; one giant memory leak.
If you use a more dedicated container, you will avoid this problem. Either write one yourself (not recommended, of course), or use boost pointer containers.
STL containers store value object. What you have here is called slicing.
You have to use vector<Base*>
because currently the objects that you pass in add will be copied into a new object of type Base
.