首页 > 解决方案 > 传递一个铸造类型

问题描述

我有一种钻石的继承。但这不是问题。我通过一个 setter 方法传递一个强制类型。但是,当我尝试将其重铸为原始类型时,我得到了 bad_cast。下面问题的代码片段。我做错了什么,我该如何解决。

#include <iostream>

class Animal {
public:
    virtual ~Animal() {}

    void SetName(const std::string name) {
        name_ = name;
    }

    std::string const &Name() {
        return name_;
    }

private:
    std::string name_;
};


class AnimalA : virtual public Animal {
public:

};

class AnimalB : virtual public Animal {
public:

};

class AnimalAB : public AnimalA, AnimalB {
public:

};

Animal h;

void GetAnimal(const Animal &animal) {
    h = animal;
}

int main() {
    Animal *animal = new AnimalA();
    GetAnimal(*animal);
     AnimalA f = dynamic_cast<AnimalA&>(h);
    return 0;
}

标签: c++

解决方案


C++ 既不是 Java 也不是 Python。在那些语言中,变量只是对对象的引用,因此它也可以包含子类的实例。C++ 有对象、指针和 2 种引用(左值和右值)。指针和引用都可以用于子类的实例,但由于切片问题,对象不能。

这里的设计问题是你有一个全局Animal 对象,你希望能够接收一个AnimalA子类的实例。这在 C++ 中根本不可能。

如果您没有所有权约束,则可以使用原始指针 for h,因为它本身就是多态的:

const Animal *h;

void GetAnimal(const Animal &animal) {
    h = &animal;
}

int main() {
    Animal *animal = new AnimalA();
    GetAnimal(*animal);
    const AnimalA *pf = dynamic_cast<const AnimalA*>(h);
    AnimalA f;
    if (pf != NULL) {
         f = *pf;       // successful copy assignment from the initial AnimalA object
    }
    del animal;         // never forget to destroy what has been allocated
    return 0;
}

如果您不想被new,del问题困扰,您可以使用自动对象而不是动态对象:

    ...
    AnimalA animal;
    GetAnimal(animal);
    ...

推荐阅读