动态转换派生类的需求:寻找替代方法

Jal*_*isa 2 c++ polymorphism inheritance

我以以下简单形式提出我的问题:

class animal {
public:
    animal() {
        _name="animal";
    }

    virtual void makenoise(){
        cout<<_name<<endl;
    }

    string get_name(){
        return _name;
    }

protected:
    string _name;
};

class cat : public animal {
public:
    cat() {
        this->_name="cat";
    }
};

class dog : public animal {
public:
    dog() {
        this->_name = "dog";
    }
};
Run Code Online (Sandbox Code Playgroud)

我想将所有动物类型一起存储在单个容器中,例如:

vector<animal*> container;
barnyard.push_back(new animal());
barnyard.push_back(new dog());
barnyard.push_back(new cat());
Run Code Online (Sandbox Code Playgroud)

在代码的某个时刻,我需要将dog对象转换为cat对象。我需要进行的转换是设置一个新的dog对象,并用与cat对应的对象相同的索引号替换它。据我了解,dynamic_cast在这种情况下不起作用,并且基于将C ++强制转换为派生类的方法,因此提到这种转换不是一种好习惯。由于模型中的猫和狗具有不同的行为特性,因此我不想将它们的定义放入动物模型中。另一方面,将它们分别存储在不同向量中将很难处理。有什么建议么?

Gui*_*cot 7

你说:

我需要将狗对象转换为猫对象。

但是之后:

我需要进行的转换是设置一个新的dog对象,并用与cat对应的对象相同的索引号替换它。

您需要转换还是替换它?这是完全不同的操作。

要进行转换,您需要设置一个将狗带回猫的函数:

auto convertDogToCat(Dog const& dog) -> Cat {
    auto cat = Cat{};

    // fill cat's member using dog's values...

    return cat; 
}
Run Code Online (Sandbox Code Playgroud)

但是要简单地用一个新的重新分配代替:

//      v--- a cat is currently there
barnyard[ii] = new Dog{};
//           ^--- we replace the old pointer
//                with one that points to a dog.
Run Code Online (Sandbox Code Playgroud)

但这会造成内存泄漏,要消除泄漏,只需使用std::unique_ptr

#include <memory> // for std::unique_ptr

// The base class need a virtual destructor
class animal {
public:
    virtual ~animal() = default;

    // other members...
};

std::vector<std::unique_ptr<animal>> barnyard;
barnyard.emplace_back(std::make_unique<animal>());
barnyard.emplace_back(std::make_unique<dog>());
barnyard.emplace_back(std::make_unique<cat>());

barnyard[ii] = std::make_unique<Dog>();
Run Code Online (Sandbox Code Playgroud)