0

My base class is called Account while the derived class Businessaccount has an additional int variable called x, as well as a getter-method (int getx()) for it. Is slicing supposed to occur in the following situation? It obviously happens in my case:

vector<shared_ptr<Account>> vec;
shared_ptr<Businessaccount> sptr = make_shared<Businessaccount>();

vec.push_back(sptr);

After that, if I do this:

(*vec.at(0)).getx();

it says that class<Account> has no member named getx()!

I'd be thankful if somebody would tell me why this occurs and how to fix it.

Rama
  • 3,222
  • 2
  • 11
  • 26
zunnzunn
  • 366
  • 1
  • 5
  • 12

3 Answers3

1

No, slicing does not happen in this situation, your pointer is just converted to pointer to a base class ie your data is the same, just type of pointer is changed. When slicing happens you loose all data of derived class.

To solve the issue you either need to provide virtual method in base class that would be properly implemented in Businessaccount or use dynamic_cast or static_cast (if you are sure that object has type Businessaccount by different matter). Though using such cast is usually sign of not well designed program.

Slava
  • 43,454
  • 1
  • 47
  • 90
0

(*vec.at(0)) is going to return an Account which doesn't know about x. You need to cast the Account pointer into a Businessaccount to reference that member.

shared_ptr<BusinessAccount> bA = dynamic_pointer_cast<BusinessAccount>(vec.at(0));
bA->getx();
lcs
  • 4,227
  • 17
  • 36
  • @FatihBAKIR [`dynamic_pointer_cast`](http://www.cplusplus.com/reference/memory/dynamic_pointer_cast) – lcs May 12 '17 at 17:52
0

In C++ the static and dynamic type of an object pointed to can differ.

Your static type of what the shared pointers in that vec point to is Account.

The dynamic type of what the shared pointers in that vec point to varies. In your case, you put a Businessaccount in it.

When you want to access or call methods, you are given access to only the static type methods.

The static type is what you have proven to the compiler the type contains at that line.

If you know better, you can do a static_cast<Businessaccount*>(vec.at(0).get())->getx(). By doing so you are promising to the compiler that you have certain knowledge that the data at that location is actually a Businessaccount. If you are wrong, your program's behavior is undefined (if you are lucky you get a crash).

You can also use RTTI (run time type information) to ask if a particular object is a particular sub-type (in some cases, where the base class has a virtual method).

Account* paccount = vec.at(0).get();
Businessaccount* pba = dynamic_cast<Businessaccount*>(paccount);
if (pba)
  pba->getx();

the above checks if the paccount is actually a Businessaccount*, and if so calls getx on it. If not, it does nothing.

Often dynamic casting is a sign you didn't design your object use properly; having to drill down past the interface into which implementation means maybe your interface wasn't rich enough.

In some scripting and bytecode compiled languages, they let you go off and call getx and proceed to crash/throw an exception/etc if that method isn't isn't there.

C++ instead lets you use what you have claimed to be there (via the type system), then lets you write your own handler if you want dynamic type checking.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524