是否有可能在将指针抽象为远离用户的同时支持多态方法调用?

问题描述 投票:0回答:1

问题

我正在尝试在我的代码中支持某种程度的多态性。我基本上想覆盖子类(strDog)中的方法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指针。换句话说,我想avoid使用户执行以下操作:

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);

是问题,因为DogDuck被切成Animal。但是,另一种方法是在指针中明确指出我们想要哪种动物,aka

std::unique_ptr<Dog> dog_ptr = std::make_unique<Dog>(Dog())
c++ c++11 pointers polymorphism smart-pointers
1个回答
1
投票

没有克隆功能,您可以这样做:

class AnimalContainer {
private:
    AnimalPtr animal_ptr;
public:
    explicit AnimalContainer(const Dog& dog){
        this->animal_ptr = std::make_unique<Dog>(dog);
    }
    // Same for Duck

    explicit AnimalContainer(AnimalPtr animal_ptr){
        this->animal_ptr = std::move(animal_ptr));
    }

    std::string str(){ return this->animal_ptr->str(); }
};

或更笼统地说:

class AnimalContainer {
private:
    AnimalPtr animal_ptr;
public:
    template <typename T>
    explicit AnimalContainer(const T& animal){
        this->animal_ptr = std::make_unique<T>(animal);
    }

    explicit AnimalContainer(AnimalPtr animal_ptr){
        this->animal_ptr = std::move(animal_ptr));
    }

    std::string str(){ return this->animal_ptr->str(); }
};
© www.soinside.com 2019 - 2024. All rights reserved.