tags:

views:

6601

answers:

8

Someone mentioned it in the IRC, but google doesn't have a good answer.

+9  A: 

Third match in google for "C++ slicing" gives me this Wikipedia article http://en.wikipedia.org/wiki/Object_slicing and this (heated, but the first few posts define the problem) : http://bytes.com/forum/thread163565.html

So it's when you assign an object of a subclass to the super class. The superclass knows nothing of the additional information in the subclass, and hasn't got room to store it, so the additional information gets "sliced off".

If those links don't give enough info for a "good answer" please edit your question to let us know what more you're looking for.

Paul
+37  A: 

"Slicing" is where you assign an object of a derived class to an instance of a base class, thereby losing part of the information - some of it is "sliced" away.

For example,

class A {
   int foo;
};

class B : public A
{
   int bar;
};

So an object of type B has two data members, foo and bar

Then if you were to write this:

B b;

A a = b;

Then the information in b about member bar is lost in a.

David Dibben
Very informative, but see http://stackoverflow.com/questions/274626#274636 for an example of how slicing occurs during method calls (which underscores the danger a little better than the plain assignment example).
Blair Conrad
+16  A: 

If You have a base class A and a derived class B, then You can do the following.

void wantAnA(A myA)
{
   // work with myA
}

B derived;
// work with the object "derived"
wantAnA(derived);

Now the method wantAnA needs a copy of derived. However, the object derived cannot be copied completely, as the class B could invent additional member variables which are not in its base class A.

Therefore, to call wantAnA, the compiler will "slice of" all additional members of the derived class. The result might be an object, You did not want to create, because

  • it may be incomplete
  • it behaves like an A-object (all special behaviour of the class B is lost)
Black
+6  A: 

The slicing problem is serious because it can result in memory corruption, and it is very difficult to guarantee a program does not suffer from it. To design it out of the language, classes that support inheritance should be accessible by reference only (not by value). The D programming language has this property.

Consider class A, and class B derived from A. Memory corruption can happen if the A part has a pointer p, and a B instance that points p to B's additional data. Then, when the additional data gets sliced off, p is pointing to garbage.

Walter Bright
Please explain how the memory corruption can occur.
mxp
i don't trust him
Johannes Schaub - litb
Given: class A { virtual void foo() { } }; class B : A { int *p; void foo() { *p = 3; } };Now, slice a B when it is assigned to A, call foo(), which calls B::foo(), and voila! Memory corruption assigning through garbage value for B::p.
Walter Bright
call foo() will call A::foo() after slicing, not B::foo() ...
Tobi
Yup, Walter is mixing pointer assignment (where A* points to a B object, so B::p is NOT lost) and object assignment (after which A::foo is called).
MSalters
I forgot that the copy ctor will reset the vptr, my mistake. But you can still get corruption if A has a pointer, and B sets that to point into B's section that gets sliced off.
Walter Bright
Walter, why don't you update your answer with this additional information.
Brad Gilbert
Good suggestion, done.
Walter Bright
This problem isn't just limited to slicing. Any classes that contain pointers are going to have dubious behaviour with a default assignment operator and copy-constructor.
Weeble
@Weeble - Which is why you override the default destructor, assignment operator and copy-constructor in these cases.
bjarkef
+1  A: 

So ... Why is losing the derived information bad? ... because the author of the derived class may have changed the representation such that slicing off the extra information changes the value being represented by the object. This can happen if the derived class if used to cache a representation that is more efficient for certain operations, but expensive to transform back to the base representation.

Also thought someone should also mention what you should do to avoid slicing... Get a copy of C++ Coding Standards, 101 rules guidlines, and best practices. Dealing with slicing is #54.

It suggests a somewhat sophisticated pattern to fully deal with the issue: have a protected copy constructor, a protected pure virtual DoClone, and a public Clone with an assert which will tell you if a (further) derived class failed to implement DoClone correctly. (The Clone method makes a proper deep copy of the polymorphic object.)

You can also mark the copy constructor on the base explicit which allows for explicit slicing if it is desired.

Steve Steiner
A: 

The slicing problem in C++ arises from the value semantics of its objects, which remained mostly due to compatibility with C structs. You need to use explicit reference or pointer syntax to achieve "normal" object behavior found in most other languages that do objects, i.e., objects are always passed around by reference.

The short answers is that you slice the object by assigning a derived object to a base object by value, i.e. the remaining object is only a part of the derived object. In order to preserve value semantics, slicing is a reasonable behavior and has its relatively rare uses, which doesn't exist in most other languages. Some people consider it a feature of C++, while many considered it one of the quirks/misfeatures of C++.

ididak
A: 

I currently met such problems, and wonder if there is a way to let compiler issue a warning/error when there is a object slice.

http://stackoverflow.com/questions/580375/how-to-generate-a-compiler-warning-error-when-object-sliced

do you guys has any idea?

Thanks

lz_prgmr
+1  A: 

It seems to me, that slicing isn't so much a problem other than when your own classes and program are poorly architected/designed.

If I pass a subclass object in as a parameter to a method, which takes a parameter of type superclass, I should certainly be aware of that and know the internally, the called method will be working with the superclass (aka baseclass) object only.

It seems to me only the unreasonable expectation that providing a subclass where a baseclass is requested, would somehow result in subclass specific results, would cause slicing to be a problem. Its either poor design in the use of the method or a poor subclass implementation. I'm guessing its usually the result of sacrificing good OOP design in favor of expediency or performance gains.

Minok