Question

What Is Object Slicing in C++? Explanation, Examples, and How to Avoid It

cppinheritancec++-faqobject-slicing

Question

In C++, what does object slicing mean, and in which situations does it occur?

For example, how does slicing affect a derived object when it is copied or assigned to a base-class object?

Short Answer

By the end of this page, you will understand what object slicing is in C++, why it happens when a derived object is copied into a base object by value, what data gets lost, and how to avoid the problem using references, pointers, and better class design.

Concept

Object slicing happens in C++ when a derived-class object is copied into a base-class object by value.

When that happens, only the base part of the object is copied. The extra members and behavior that belong to the derived class are sliced off.

Why this happens

A derived object contains:

  • the base-class portion
  • plus its own additional data and behavior

If you create a separate base object from that derived object, the new object can only store the base portion. The derived-specific part does not fit inside a plain base object.

Example idea

If Dog inherits from Animal, then a Dog object contains an Animal part plus anything specific to Dog.

If you do this:

Dog d;
Animal a = d;

then a becomes a standalone Animal object. It is not a Dog. The Dog-specific state is lost.

Why it matters

Object slicing can cause:

  • loss of derived-class data
  • unexpected behavior when calling methods
  • bugs in containers or function calls that copy polymorphic objects by value

This is especially important in object-oriented C++ code that uses inheritance and polymorphism.

Mental Model

Think of a derived object as a larger box that contains a smaller base box inside it.

  • Base = the inner box
  • Derived = the inner box plus extra space

When you copy a Derived object into a Base variable, C++ only copies the inner Base box.

The extra part of the larger box is left behind.

That is why it is called slicing: the derived-specific part is cut off, and only the base part remains.

Take Quiz

Syntax and Examples

The key rule is simple:

Slicing occurs with copy by value

class Base {
public:
    int x = 1;
};

class Derived : public Base {
public:
    int y = 2;
};

int main() {
    Derived d;
    Base b = d;   // object slicing
}

Here, b only stores the Base part of d. The y member does not exist in b.

Example with methods

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void speak() const {
        cout << "Animal sound\n";
    }
};

class Dog : public Animal {
public:
    void speak() const override {
        cout << "Woof\n";
    }
};

int main() {
    Dog dog;
    Animal animal = dog;  // slicing

    dog.speak();
    animal.speak();
}

Output:

Woof
Animal sound

Even though dog started as a Dog, the variable animal is a separate Animal object after copying. The Dog part was sliced away.

How to avoid slicing

Use a reference or pointer instead of copying by value.

Reference

Animal& animalRef = dog;
animalRef.speak();  // Woof

Pointer

Animal* animalPtr = &dog;
animalPtr->speak(); // Woof

In both cases, no new base object is created. You are referring to the original Dog object, so the full object remains intact.

Step by Step Execution

Consider this example:

#include <iostream>
using namespace std;

class Base {
public:
    int a = 10;
};

class Derived : public Base {
public:
    int b = 20;
};

int main() {
    Derived d;
    Base baseObj = d;

    cout << baseObj.a << "\n";
}

Step by step

  1. Derived d;

    • A Derived object is created.
    • It contains:
      • the Base part with a = 10
      • the Derived part with b = 20
  2. Base baseObj = d;

    • A new object of type Base is created.
    • C++ copies only the Base portion from d into baseObj.
    • The member b is not copied because Base has no b.
  3. cout << baseObj.a;

    • This prints 10.

Important observation

You cannot do this afterward:

cout << baseObj.b;

because baseObj is just a Base object. The derived part no longer exists in that copied object.

Trace summary

VariableActual typeContains
dDeriveda and b
baseObjBaseonly a

That difference is the essence of object slicing.

Real World Use Cases

Object slicing often appears accidentally in real programs.

1. Passing objects to functions by value

void printAnimal(Animal a) {
    a.speak();
}

If you call printAnimal(dog);, the Dog object is sliced into an Animal copy.

Better:

void printAnimal(const Animal& a) {
    a.speak();
}

2. Storing derived objects in a container of base objects

vector<Animal> animals;
animals.push_back(Dog());  // slicing

Each element in vector<Animal> is an actual Animal object, so derived parts are lost.

Better approaches:

  • vector<Animal*>
  • vector<shared_ptr<Animal>>
  • vector<unique_ptr<Animal>>

3. Returning base objects by value

Animal makeAnimal() {
    Dog d;
    return d; // slicing
}

The returned object is an Animal, not a Dog.

4. Assigning derived to base variables

Dog d;
Animal a;
a = d;  // slicing through assignment

This also copies only the base portion.

These situations are common in APIs, class hierarchies, and container design.

Take Quiz

Real Codebase Usage

In real C++ codebases, developers usually avoid polymorphic objects being copied by value.

Common patterns

Pass base types by reference

void process(const Animal& animal) {
    animal.speak();
}

This avoids copying and preserves polymorphism.

Store polymorphic objects through pointers

#include <memory>
#include <vector>

vector<unique_ptr<Animal>> animals;
animals.push_back(make_unique<Dog>());

This keeps the real runtime type.

Use virtual destructors in polymorphic base classes

class Animal {
public:
    virtual ~Animal() = default;
    virtual void speak() const = 0;
};

If you use base pointers or references, a virtual destructor is important for correct cleanup.

Prevent copying in polymorphic bases when appropriate

Some designs delete copy operations or make the base abstract so accidental slicing becomes less likely.

class Animal {
public:
    Animal() = default;
    Animal(const Animal&) = default;
    virtual ~Animal() = default;
    virtual void speak() const = 0;
};

Or developers may document clearly that objects should be handled via references or smart pointers.

Guarding against bugs

Teams often review for patterns like:

  • function parameters of polymorphic base type by value
  • vector<Base> used with derived objects
  • factory functions returning Base by value

These are common places where slicing slips into production code.

Common Mistakes

1. Passing a base class by value

Broken code:

void makeSpeak(Animal a) {
    a.speak();
}

Problem:

  • Passing by value creates a new Animal object.
  • A Dog argument gets sliced.

Fix:

void makeSpeak(const Animal& a) {
    a.speak();
}

2. Using vector<Base> for polymorphic objects

Broken code:

vector<Animal> animals;
animals.push_back(Dog());
animals.push_back(Cat());

Problem:

  • The container stores actual Animal objects.
  • Dog and Cat parts are sliced off.

Fix:

vector<unique_ptr<Animal>> animals;
animals.push_back(make_unique<Dog>());
animals.push_back(make_unique<Cat>());

3. Assuming virtual functions prevent slicing

Broken assumption:

Dog d;
Animal a = d; // still slices

Problem:

  • virtual enables dynamic dispatch through references or pointers.
  • It does not stop object copying by value.

4. Returning base by value from a polymorphic factory

Broken code:

Animal createAnimal() {
    return Dog();
}

Fix:

unique_ptr<Animal> createAnimal() {
    return make_unique<Dog>();
}

5. Forgetting that assignment can also slice

Dog d;
Animal a;
a = d; // slicing

Beginners often notice slicing during initialization but forget it also happens during assignment to an existing base object.

How to avoid these mistakes

  • Pass polymorphic objects by reference or pointer
  • Store polymorphic objects via pointers, usually smart pointers
  • Be careful with Base parameters and return types by value
  • Review containers and APIs for hidden copies

Comparisons

SituationSlicing?Why
Base b = derived;YesCreates a new base object by value
Base& b = derived;NoReference refers to original derived object
Base* b = &derived;NoPointer points to original derived object
void f(Base b)YesFunction parameter copies by value
void f(const Base& b)NoNo copy is made
vector<Base> with derived insertsYesContainer stores base objects
vector<unique_ptr<Base>>NoStores pointers to real derived objects

Object slicing vs polymorphism

ConceptMeaning
Object slicingDerived part is lost because a copy is made into a base object
PolymorphismA base reference or pointer can call derived behavior through virtual functions

Base object vs base reference

FormKeeps derived data?Keeps dynamic behavior?
Base obj = derived;NoNo
Base& ref = derived;YesYes
Base* ptr = &derived;YesYes
Take Quiz

Cheat Sheet

Quick definition

Object slicing happens when a derived object is copied into a base object by value, causing the derived-specific part to be lost.

Common slicing cases

Base b = derived;
Base b(derived);
b = derived;
void func(Base b);   // slicing if called with derived
vector<Base> items;
items.push_back(derived); // slicing

Safe alternatives

void func(const Base& b);
void func(Base* b);
Base& ref = derived;
Base* ptr = &derived;
vector<unique_ptr<Base>> items;

Key rule

  • By value can slice
  • By reference does not slice
  • By pointer does not slice

Important note

virtual functions do not prevent slicing. They only work correctly when using base references or pointers.

Best practices

  • Pass polymorphic types by const Base&
  • Store polymorphic objects with smart pointers
  • Avoid returning polymorphic base objects by value

FAQ

What is object slicing in simple terms?

Object slicing is when a derived object is copied into a base object, and the derived-specific part is lost.

When does object slicing occur in C++?

It occurs when a derived object is passed, returned, assigned, or stored by value as a base type.

Does object slicing happen with references?

No. References do not create a new base object, so the full derived object remains intact.

Does object slicing happen with pointers?

No. A pointer just points to the original object, so no slicing occurs.

Do virtual functions stop object slicing?

No. Virtual functions help with dynamic dispatch, but they do not stop copying a derived object into a base object.

Can STL containers cause object slicing?

Yes. For example, vector<Base> will slice derived objects inserted by value.

How do I avoid object slicing in C++?

Use references or pointers for polymorphic types, and prefer smart pointers in containers and factory functions.

Is slicing always a bug?

Usually in polymorphic designs, yes. In some rare cases, copying only the base part may be intentional, but it should be a deliberate design choice.

Take Quiz

Mini Project

Description

Build a small C++ program that demonstrates object slicing and then fixes it. The program will model animals with a base class and a derived class. First, you will pass a derived object to a function by value and observe the slicing. Then you will change the function to use a reference and compare the result. This project is useful because it shows the exact bug beginners often encounter in class hierarchies.

Goal

Create a program that shows the difference between passing a derived object by value and by reference in C++.

Requirements

  • Create a base class with a virtual method.
  • Create a derived class that overrides that method.
  • Write one function that accepts the base type by value.
  • Write another function that accepts the base type by reference.
  • Call both functions with a derived object and compare the output.
Take Quiz

Keep learning

Related questions

View more