Как сохранить использование метода дочерних классов после создания указателя на базовый класс? - PullRequest
0 голосов
/ 21 января 2020

Когда я создаю указатель Animal для хранения объекта Duck и использую метод make_choice, который возвращает enum, создается впечатление, что вместо этого используется метод, принадлежащий базовому классу Animal производного Duck класса. Как вместо этого сохранить использование метода производных классов?


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

using namespace std;

enum Choice{None, Egg, Bone};
class Animal {

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

    virtual ~Animal() = default;

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

    virtual Choice make_choice(){
        return None;
    }

};

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

    Choice make_choice() override {
        return Egg;
    }
};


int main() {
    Duck duck;
    cout << duck.make_choice() << endl; // should be 1 for Egg
    std::shared_ptr<Animal> duckPtr = std::make_shared<Animal>(duck);
    cout << duckPtr->make_choice() << endl; // also should be 1 for Egg, but is 0 for None
    return 0;
};

Вывод:

1 // for Egg
0 // for None

1 Ответ

2 голосов
/ 21 января 2020

std::make_shared<Animal>(duck); не сделал Duck. Он сделал Animal, сделав копию duck и Объектная нарезка , удалив все, что отличает Duck от Animal.

Вы хотите

std::shared_ptr<Animal> duckPtr = std::make_shared<Duck>(duck);

или просто

std::shared_ptr<Animal> duckPtr = std::make_shared<Duck>();

Адресация Но что, если указатель впоследствии необходимо будет сохранить в массиве указателей Animal? из комментариев

std::shared_ptr<Animal> animals[2];

animals[0] = duckPtr;

совершенно законно. Никаких дополнительных работ не требуется.

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