answersLogoWhite

0

Object slicing typically occurs when operating upon a base class reference, even when the reference is actually an instance of a derived class. You might expect polymorphic behaviour but it doesn't happen, due to object slicing. Most of the time this is only to be expected (such as when passing a derived object to a base class copy constructor or assignment operator), but when you actually expect polymorphic behaviour it can catch you out. The following example of partial assignment demonstrates this:

#include

struct A {

int a_var;

A(int a): a_var(a) {}

void debug() { std::cout<<"a_var="<

A& operator=(const A& rhs){ a_var=rhs.a_var; std::cout<<"Copying from A"<

};

struct B : public A {

int b_var;

B(int a, int b): A(a), b_var(b) {}

void debug() { A::debug(); std::cout<<" b_var="<

A& operator=(const B& rhs){ A::operator=(rhs); b_var=rhs.b_var; std::cout<<"Copying from B"<

};

int main()

{

B b1(1,2);

B b2(3,4);

std::cout<<"b1 : "; b1.debug(); std::cout<

std::cout<<"b2 : "; b2.debug(); std::cout<

A& ref=b1;

ref=b2;

std::cout<<"b1 : "; b1.debug(); std::cout<

std::cout<<"b2 : "; b2.debug(); std::cout<

}

In the above example, it may seem that b1 and b2 should be equal since we've assigned b2 to a reference to b1. But because the reference is actually to the base class, A, rather than the derived class, B, the object is sliced and only A::a_var is copied; base class A has no storage for B::b_var. The output clearly shows that only the A assignment operator is executed:

b1 : a_var=1 b_var=2

b2 : a_var=3 b_var=4

Copying from A

b1 : a_var=3 b_var=2

b2 : a_var=3 b_var=4

To fix this, we must reference the derived class B instead of the base class A. Thus we must replace the line A& ref=b1; with B& ref=b1;.

The output then becomes:

b1 : a_var=1 b_var=2

b2 : a_var=3 b_var=4

Copying from A

Copying from B

b1 : a_var=3 b_var=4

b2 : a_var=3 b_var=4

In this trivial example the problem is patently obvious but when passing references around functions it may not be entirely clear exactly why the behaviour is not as expected. Remember that if you pass references to base classes you are expected to operate upon the base class only. If you expect polymorphic behaviour, you must use virtual methods to perform the operations instead. The only other option is to invoke runtime type information, which only serves to impede performance and is really a sign of poor design.

User Avatar

Wiki User

11y ago

What else can I help you with?