C++ Object Slicing Simplified
- Sunil Kumar Yadav

- 20 hours ago
- 3 min read

Object-oriented programming and polymorphism are fundamental concepts in C++. Most developers learn that virtual functions allow derived classes to provide specialized implementations while interacting through a base class interface.
However, there is a subtle issue that can silently break polymorphism: Object Slicing.
In this article, we'll understand what object slicing is, why it happens, and how to avoid it using a few simple examples.
What is Object Slicing?
Object slicing occurs when a derived class object is copied into a base class object by value.
During this copy operation, only the base class portion of the object is preserved. Any data and behavior specific to the derived class are discarded (or "sliced off").
Let's look at an example.
#include <iostream>
class Vehicle
{
public:
virtual void Print() const
{
std::cout << "Vehicle" << std::endl;
}
};
class Car : public Vehicle
{
public:
void Print() const override
{
std::cout << "Car" << std::endl;
}
};
int main()
{
Car car;
Vehicle vehicle = car;
vehicle.Print();
}
Output:
VehicleMany developers expect the output to be:
Carbut that's not what happens. The reason is that the statement below creates a new Vehicle object:
Vehicle vehicle = car;Only the Vehicle portion of car is copied into vehicle. As a result, the object stored in vehicle is no longer a Car. It is simply a Vehicle.
If you are using classes you must pass references to avoid object slicing. — Bjarne Stroustrup, Creator of C++
Visualizing Object Slicing
Consider the following classes:
class Base
{
int a;
};
class Derived : public Base
{
int b;
};
A Derived object can be visualized as:
+---------+
| Base::a |
+---------+
| b |
+---------+
When we write:
Base obj = derived;
the resulting object becomes:
+---------+
| Base::a |
+---------+
The member b no longer exists in the copied object. This loss of derived-class information is called object slicing.
A Common Real-World Example
Object slicing frequently occurs when objects are passed by value. Consider the following code:
#include <iostream>
class Animal {
public:
virtual void Speak() const {
std::cout << "Animal Sound" << std::endl;
}
};
class Dog : public Animal {
public:
void Speak() const override {
std::cout << "Bark Bark" << std::endl;
}
};
void MakeAnimalSpeak(Animal animal) {
animal.Speak();
}
int main() {
Dog dog;
MakeAnimalSpeak(dog);
}
Output:
Animal SoundAt first glance, this may seem surprising. The function parameter:
Animal animalcreates a copy of the argument. Before entering the function, the Dog object is sliced into an Animal object. Consequently, the virtual dispatch mechanism only sees an Animal object and invokes:
Animal::Speak()instead of:
Dog::Speak()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). — Walter Bright, Creator of the D programming language
The Correct Approach
The most common solution is to pass objects by reference.
void MakeAnimalSpeak(const Animal& animal) {
animal.Speak();
}Now running the same program produces:
Bark BarkSince no copy is created, no slicing occurs. The reference continues to refer to the original Dog object, allowing virtual dispatch to work correctly.
Object Slicing in STL Containers
Another place where developers accidentally encounter slicing is when storing polymorphic objects in containers. Consider:
std::vector<Shape> shapes;
shapes.push_back(Circle());The Circle object is copied into a Shape object stored inside the vector. The derived portion is discarded. A better approach is:
std::vector<std::unique_ptr<Shape>> shapes;or
std::vector<std::shared_ptr<Shape>> shapes;
This preserves polymorphic behavior and avoids slicing.
Conclusion
Object slicing occurs whenever a derived object is copied into a base object by value.
Common situations include:
Assigning a derived object to a base object
Passing polymorphic objects by value
Returning base objects by value
Storing polymorphic objects in containers by value
To avoid object slicing:
Prefer references (Base&)
Prefer pointers (Base*)
Use smart pointers (std::unique_ptr, std::shared_ptr) when ownership is required
Avoid passing polymorphic types by value
Object slicing is not a compiler error. The code compiles successfully and often appears to work correctly. This makes it one of those subtle C++ issues that every developer should understand, especially when working with inheritance and polymorphism.




Comments