c++ - 传递一个铸造类型
问题描述
我有一种钻石的继承。但这不是问题。我通过一个 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++ 既不是 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);
...