CiaranWelsh
CiaranWelsh

Reputation: 7681

How to retain use of a child classes method after being made a pointer to the base class?

When I make an Animal pointer to hold a Duck object and use a method make_choice that returns an enum, it looks as though the method belonging to the base Animal class is being used instead of the derived Duck class. How do I instead retain use of the derived classes method?


#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;
};

Output:

1 // for Egg
0 // for None

Upvotes: 0

Views: 29

Answers (1)

user4581301
user4581301

Reputation: 33952

std::make_shared<Animal>(duck); did not make a Duck. It made an Animal by making a copy of duck and Object Slicing away everything that makes a Duck different from an Animal.

You want

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

or just

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

Addressing But what if the pointer later needs to be stored in an array of Animal pointers? from the comments,

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

animals[0] = duckPtr;

is perfectly legal. No extra work is required.

Upvotes: 2

Related Questions