본문으로 건너뛰기 C++ Slicing Problem — Complete Guide

C++ Slicing Problem — Complete Guide

C++ Slicing Problem — Complete Guide

이 글의 핵심

C++ slicing problem C++, slicing, "object, Introduction: "Copied derived class but data disappeared" explained in detail with practical examples.

Introduction: “Copied Derived Class but Data Disappeared"

"Polymorphism Not Working”

In C++, when copying derived class object to base class type, derived class members get sliced off causing slicing problem.

// ❌ Slicing problem
class Animal {
public:
    virtual void speak() {
        std::cout << "Animal sound\n";
    }
};

class Dog : public Animal {
    std::string name_;
public:
    Dog(const std::string& name) : name_(name) {}
    
    void speak() override {
        std::cout << name_ << " barks\n";
    }
};

void makeSound(Animal animal) {  // ❌ Pass by value
    animal.speak();
}

int main() {
    Dog dog("Buddy");
    makeSound(dog);  // ❌ Slicing occurs
    // Output: Animal sound (Dog got sliced!)
}

What This Guide Covers:

  • What is slicing problem?
  • Polymorphism loss
  • Solution with reference/pointer
  • Copy prevention pattern

1. What is Slicing Problem?

Slicing Occurs

class Base {
public:
    int x = 1;
    virtual void foo() {
        std::cout << "Base::foo\n";
    }
};

class Derived : public Base {
public:
    int y = 2;  // Derived class member
    void foo() override {
        std::cout << "Derived::foo\n";
    }
};

int main() {
    Derived d;
    Base b = d;  // ❌ Slicing occurs
    
    std::cout << b.x << '\n';  // 1
    // std::cout << b.y << '\n';  // Compile error: no y
    
    b.foo();  // Base::foo (polymorphism lost)
}

Problems:

  • y member lost
  • Polymorphism lost (virtual ignored)
  • vtable pointer not copied

2. Polymorphism Loss

Example 1: Function Argument

// ❌ Pass by value
void process(Animal animal) {  // Slicing
    animal.speak();  // Animal::speak called
}

Dog dog("Buddy");
process(dog);  // Animal sound (polymorphism lost)

// ✅ Pass by reference
void process(Animal& animal) {  // No slicing
    animal.speak();  // Dog::speak called
}

process(dog);  // Buddy barks (polymorphism preserved)

Example 2: Container

// ❌ vector<Base>
std::vector<Animal> animals;
animals.push_back(Dog("Buddy"));  // Slicing
animals[0].speak();  // Animal sound

// ✅ vector<unique_ptr<Base>>
std::vector<std::unique_ptr<Animal>> animals;
animals.push_back(std::make_unique<Dog>("Buddy"));
animals[0]->speak();  // Buddy barks

3. Solution: Reference/Pointer

Solution 1: Use Reference

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

Dog dog("Buddy");
process(dog);  // Buddy barks

Solution 2: Use Pointer

// ✅ Pointer
void process(Animal* animal) {
    if (animal) {
        animal->speak();
    }
}

Dog dog("Buddy");
process(&dog);  // Buddy barks

Solution 3: Smart Pointer

// ✅ unique_ptr
void process(std::unique_ptr<Animal> animal) {
    animal->speak();
}

process(std::make_unique<Dog>("Buddy"));  // Buddy barks

// ✅ shared_ptr
void process(std::shared_ptr<Animal> animal) {
    animal->speak();
}

process(std::make_shared<Dog>("Buddy"));  // Buddy barks

4. Copy Prevention Pattern

Pattern 1: Delete Copy Constructor

class Animal {
public:
    Animal() = default;
    Animal(const Animal&) = delete;  // Prevent copy
    Animal& operator=(const Animal&) = delete;
    
    virtual ~Animal() = default;
    virtual void speak() = 0;
};

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

int main() {
    Dog dog;
    // Animal a = dog;  // Compile error
}

Summary

Key Points

  1. Slicing: Derived members lost when copying to base type
  2. Polymorphism loss: Virtual functions ignored
  3. Solution: Use reference or pointer
  4. Prevention: Delete copy constructor
  5. Container: Store pointers, not objects

When to Use

Prevent slicing by:

  • Using reference/pointer
  • Deleting copy constructor
  • Using smart pointers
  • Storing pointers in containers

Don’t:

  • Pass polymorphic objects by value
  • Store polymorphic objects directly in containers
  • Copy derived to base type

Best Practices

  • ✅ Always use reference/pointer for polymorphism
  • ✅ Delete copy constructor in base class
  • ✅ Use smart pointers for ownership
  • ❌ Don’t pass polymorphic objects by value
  • ❌ Don’t store objects in vector

Master slicing prevention for safer C++ polymorphism! 🚀


Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. Everything about C++ Slicing Problem : from basic concepts to practical applications.

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers C++, slicing, inheritance, polymorphism, copy, reference, pointer.