Как правильно реализовать изменение элемента в классе контейнера? - PullRequest
1 голос
/ 20 января 2020

Я строю контейнерный тип, который содержит указатели на иерархию классов. Моя проблема в том, что я не могу изменить элемент, используя что-то вроде:

container[0] = x

Вот минимальный пример, который воспроизводит мою проблему.

#include <iostream>
#include <vector>
#include <memory>

using namespace std;


class Animal {

protected:
    std::string noise = "None";
public:
    Animal() = default;

    virtual ~Animal() = default;

    virtual std::string getNoise() {
        return noise;
    }

};

class Duck : public Animal {
public:
    Duck() {
        noise = "Quack!";
    }
};


class Dog : public Animal {
public:
    Dog() {
        noise = "Bark!";
    }
};

class Cat : public Animal {
public:
    Cat() {
        noise = "Me-thefuck-ow!";
    }

    Cat& operator=(Cat const& other) {
        noise = other.noise;
        return *this;
    }
};

typedef std::shared_ptr<Animal> AnimalPtr;


class AnimalsContainer {
public:
    std::vector<AnimalPtr> animals;
    AnimalPtr front;
    Duck duck;
    Dog dog;

    AnimalsContainer() {
        animals.push_back(std::make_unique<Animal>(duck));
        animals.push_back(std::make_unique<Animal>(dog));
        front = animals[0];
    }
    AnimalsContainer(AnimalsContainer& animalsContainer) = default;
    ~AnimalsContainer() = default;
    AnimalsContainer& operator=(const AnimalsContainer&  animalsContainer) = default;
    AnimalsContainer& operator=(AnimalsContainer&& animalsContainer) = default;

    AnimalPtr operator[](int index){
        return animals[index];
    }
};


int main() {
    AnimalsContainer animalsContainer;

    cout << animalsContainer[0]->getNoise() << endl;

    Cat cat;
    animalsContainer[0] = std::make_unique<Animal>(cat);

    cout << animalsContainer[0]->getNoise() << endl;
    return 0;
}

Это выводит:

Quack!
Quack!

Где я хочу:

Quack!
Meow!

1 Ответ

3 голосов
/ 20 января 2020

Здесь:

AnimalPtr operator[](int index) {
    return animals[index];
}

Вы возвращаетесь по значению, тогда копии назначается новое значение. Предполагается, что вы должны вернуть ссылку:

AnimalPtr& operator[](int index) {
    return animals[index];
}

Также вы, вероятно, намеревались использовать make_shared вместо make_unique во всех случаях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...