# Slicing **Object slicing** happens when a derived-class object is copied into a base-class object by value: only the base subobject gets copied, and everything the derived class added is silently discarded ("sliced off"). The code compiles cleanly and runs without crashing, which is exactly what makes it a dangerous, experience-only trap rather than something a beginner learns from a compiler error. ```cpp struct Base { int x = 1; virtual void print() const { std::cout << "Base\n"; } }; struct Derived : Base { int y = 2; void print() const override { std::cout << "Derived\n"; } }; void byValue(Base b) { b.print(); } // takes Base by value Derived d; byValue(d); // prints "Base", not "Derived" — d was sliced to a Base ``` ## Why virtual dispatch doesn't save it Virtual functions dispatch based on an object's actual dynamic type, but that only works through a pointer or reference to the object, not when the object itself has been copied into a differently-typed variable. `byValue(Base b)` constructs a genuine, separate `Base` object using `Base`'s copy constructor; the `y` member and the overridden `print()` behavior never existed on that object in the first place, there is no dynamic type left to dispatch on. This is different from the usual "did I forget `virtual`" mistake: slicing happens even with a fully correct virtual function setup, because the problem is the by-value parameter, not the missing keyword. ```cpp void byRef(const Base &b) { b.print(); } // takes Base by reference byRef(d); // prints "Derived" — no copy, no slicing, virtual dispatch works ``` ## Where it actually bites Slicing shows up most often in container code and generic algorithms that quietly copy by value: pushing a `Derived` into a `std::vector` slices every element on insertion, and a function template parameter deduced or declared as `Base` rather than `Base&` slices on every call, even though nothing in the code looks wrong at a glance. The standard defense is polymorphic types should be passed and stored by reference or pointer (commonly a smart pointer like [[unique-ptr]] or [[shared-ptr]]), never by value, and a class meant to be used polymorphically should make that intent explicit by deleting or protecting its copy constructor if slicing would never be correct for it. ## Links - https://en.cppreference.com/w/cpp/language/object_slicing.html