Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 需要对派生类进行动态强制转换:寻找替代方法_C++_Inheritance_Polymorphism - Fatal编程技术网

C++ 需要对派生类进行动态强制转换:寻找替代方法

C++ 需要对派生类进行动态强制转换:寻找替代方法,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,我以这种简单的形式提出我的问题: class animal { public: animal() { _name="animal"; } virtual void makenoise(){ cout<<_name<<endl; } string get_name(){ return _name; } protected: string _name; }; cla

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

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";
    }
};
类动物{
公众:
动物(){
_name=“动物”;
}
虚拟void makenoise(){
你能说:

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

但是:

从这个转换中,我所需要的就是设置一个新的dog对象,并将其替换为与cat对应对象相同的索引号

你需要转换还是替换它?那是完全不同的操作

要转换,您需要设置一个函数,该函数将接收一只狗并返回一只猫:

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

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

    return cat; 
}
但要简单地用新的重新分配来代替:

//      v--- a cat is currently there
barnyard[ii] = new Dog{};
//           ^--- we replace the old pointer
//                with one that points to a dog.
但这会造成内存泄漏,要消除泄漏,只需使用
std::unique\u 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>();
\include//for std::unique\u ptr
//基类需要一个虚拟析构函数
类动物{
公众:
virtual~animal()=默认值;
//其他成员。。。
};
std::矢量谷仓;
barnyard.emplace_back(std::make_unique());
barnyard.emplace_back(std::make_unique());
barnyard.emplace_back(std::make_unique());
barnyard[ii]=std::make_unique();

这里有一种替代方法。不使用OOP或动态调度,但为示例提供了相同的功能。速度也快得多,因为不需要动态内存来分配/释放,动物是单字节的

enum struct eAnimalKind : uint8_t
{
    Generic = 0,
    Cat = 1,
    Dog = 2,
};

string get_name( eAnimalKind k )
{
    static const std::array<string, 3> s_names =
    {
        "animal"s, "cat"s, "dog"s
    };
    return s_names[ (uint8_t)k ];
}

void makenoise( eAnimalKind k )
{
    cout << get_name( k ) << endl;
}
枚举结构eAnimalKind:uint8\t { 通用=0, Cat=1, 狗=2, }; 字符串获取名称(eAnimalKind k) { 静态常量std::数组s_名称= { 动物的,猫的,狗的 }; 返回s_名称[(uint8_t)k]; } void makenoise(eAnimalKind k) {
把一只狗变成一只猫有什么意义?如果你需要一只狗在猫所在的地方,只需删除猫并插入一只狗。Vector你能提供一些背景资料说明为什么你需要这样的替代品吗?必须用
替换所有
,这让我觉得这是一个共同的集合,两者都存储为
animal
不是正确的选择,因为它会丢失信息(这会导致您以后需要动态强制转换),动态强制转换不会转换任何对象。给定基类指针,它会给您一个指向派生类的指针(如果基类不是派生类型,则为null)。这与转换对象无关(在你的简单例子中,这也没有任何意义)。我想你可能对对象和指向对象的指针有一些混淆。@SergeyA是的,试图抹去猫身上的污垢可能会很痛苦。这就是为什么我要养狗的原因;)这是一个很好的方法,但不适合我的问题的复杂性reasons@JalilNourisa
std::variant
在这方面非常好:让您拥有一个多类型的对象,而无需动态分配。我发现它比继承+虚拟分派(如果适用)简单得多。它大大降低了复杂性。
enum struct eAnimalKind : uint8_t
{
    Generic = 0,
    Cat = 1,
    Dog = 2,
};

string get_name( eAnimalKind k )
{
    static const std::array<string, 3> s_names =
    {
        "animal"s, "cat"s, "dog"s
    };
    return s_names[ (uint8_t)k ];
}

void makenoise( eAnimalKind k )
{
    cout << get_name( k ) << endl;
}