Search code examples
c++overridingrepository-patternvirtual-functionsobject-slicing

How to overcome object slicing in repository pattern?


I have the following piece of code:

#include <iostream>

class AnimalRepository {
public:
    virtual ~AnimalRepository() = default;

    virtual auto makeSound() -> void {
        std::cout << "Null" << std::endl;
    }

};

class CatRepository: public AnimalRepository {
public:
   
    auto makeSound() -> void override {
       std::cout << "Meow" << std::endl;
    }

};

class DogRepository: public AnimalRepository {
public:

    auto makeSound() -> void override {
        std::cout << "Woof" << std::endl;
    }

};

class Animal {
public:
    explicit Animal(const AnimalRepository& repository)
            : repository(repository) {
    }

    auto makeSound() -> void {
        return repository.makeSound();
    }

protected:
    AnimalRepository repository;
};

Animal cat = Animal(CatRepository());

Animal dog = Animal(DogRepository());

int main() {
    cat.makeSound();
    dog.makeSound();
};

I expected the main function to output the respective cat and dog method override functions, but instead it always returns "Null". I believe this is a case of object slicing, and I'm not quite sure I understand why the reference pointer in the Animal class constructor doesn't avoid this issue.


Solution

  • The slicing is done here: AnimalRepository repository;. This can't contain a subclass because it is an instance and not a reference or pointer. It is easiest to replace this with a unique smart pointer pointing to a copy of the input.