yegor256
yegor256

Reputation: 105210

What is a possible workaround for object slicing in c++?

This is the code:

#include <string>
#include <vector>
#include <iostream>
using namespace std;
class A {
public:
  virtual const string f() const { return "A"; }
};
class B : public A {
public:
  const string f() const { return "B"; }
};
int main(int ac, char** av) {
  vector<A> v;
  v.push_back(B());
  cout << v.at(0).f() << endl;
  return 0;
}

Expected result is B, but it's A. As I understand object slicing is taking place. How to avoid it? Shall I store pointers in vector instead of object instances? Is this the only choice?

Upvotes: 8

Views: 5115

Answers (3)

Kornel Kisielewicz
Kornel Kisielewicz

Reputation: 57635

Ordered from most simple, to most complex (but most nice).

Solution 1:

vector<B> v;
v.push_back(B());
cout << v.at(0).f() << endl;

Solution 2:

vector<A*> v;
v.push_back(new B());
cout << v.at(0)->f() << endl;
while(!v.empty()) { delete v.back(); v.pop_back(); }

Solution 3:

vector<boost::shared_ptr<A>> v;
v.push_back(boost::make_shared<B>());
cout << v.at(0)->f() << endl;

If you don't want slicing to happen, you need to take into account the fact that different objects may have different sizes -- ergo you need a solution that can work with variable sizes -- that makes storing on the heap a must.

Upvotes: 14

anon
anon

Reputation:

Well, in your code you could use a vector of B. Note that virtual functions will only be dispatched properly if called via a pointer or a reference. However, assuming you really want your vector to contain both A and B objects, you need to make it vector of A pointers, and create the A and B objects dynamically.

Upvotes: 3

sbi
sbi

Reputation: 224199

You need to store pointers. If these refer to dynamically allocated objects, use smart pointers.

Upvotes: 14

Related Questions