Home > Mobile >  How to overcome object slicing in repository pattern?
How to overcome object slicing in repository pattern?

Time:01-05

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.

CodePudding user response:

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.

CodePudding user response:

Or move the whole pattern from dynamic polymorphism to (compile time) static polymorphism

#include <iostream>

class CatBehavior 
{
public:

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

};

class DogBehavior 
{
public:

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

template<typename behavior_t>
class Animal 
{
public:
    explicit Animal() 
    {
    }

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

protected:
    behavior_t m_behavior;
};

int main() 
{
    Animal<CatBehavior> cat;
    Animal<DogBehavior> dog;

    cat.makeSound();
    dog.makeSound();
};
  • Related