Проблема
Я пытаюсь поддерживать некоторую степень полиморфизма в моем коде. Я в основном хочу переопределить метод str
в подклассах (Dog
и Duck
) и затем использовать умный указатель на суперкласс Animal
в другом классе (AnimalContainer
) для вызова метода str
. В частности, я хочу поддержать следующий API:
int main(){
Duck duck;
Dog dog;
AnimalContainer duckInContainer(duck);
std::cout << duckInContainer.str() << std::endl; // Outputs "None" but should output "Duck"
AnimalContainer dogInContainer(dog);
std::cout << dogInContainer.str() << std::endl; // Outputs "None" but should output "Dog"
}
Отсутствие указателей здесь является преднамеренным. Я намерен сделать это интерфейсом API и хочу сделать его максимально простым. Поэтому, если возможно, я хочу, чтобы пользователи явно не создавали (скажем) указатель Dog
. Другими словами, я бы хотел избегать заставления пользователей делать что-то вроде этого:
Dog dog;
std::unique_ptr<Dog> dog_ptr = std::make_unique<Dog>(dog);
AnimalContainer animalContainer(dog_ptr)
std::cout << animalContainer.str() << std::endl;
Возможно ли вышеизложенное, и если да, то какие изменения мне нужно внести в следующее код:
код
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Animal {
public:
Animal() = default;
virtual std::string str() {
return "None";
}
};
class Duck : public Animal {
public:
using Animal::Animal;
std::string str() override {
return "Duck";
}
};
class Dog : public Animal {
public:
using Animal::Animal;
std::string str() override {
return "Dog";
}
};
typedef std::unique_ptr<Animal> AnimalPtr;
class AnimalContainer {
private:
AnimalPtr animal_ptr;
public:
explicit AnimalContainer(const Animal& animal){
this->animal_ptr = std::make_unique<Animal>(animal);
}
explicit AnimalContainer(AnimalPtr animal_ptr){
this->animal_ptr = std::make_unique<Animal>(*animal_ptr);
}
std::string str(){
return this->animal_ptr->str();
}
};
До сих пор я думаю, что эта строка
this->animal_ptr = std::make_unique<Animal>(animal);
является проблемой, так как Dog
или Duck
нарезается до Animal
. Тем не менее, альтернатива, которая является явным о том, какой тип животного мы хотим в указателе ака
std::unique_ptr<Dog> dog_ptr = std::make_unique<Dog>(Dog())