为什么此C ++代码不起作用?它旨在将基类动态转换为派生类。我将如何实现?
class base {
public:
int x = 0;
};
class a : public base {
public:
char c = 'a';
};
class b : public base {
public:
long int d = 'b';
};
std::vector<base> vec;
for (int i = 0; i < 5; i++) {
b temp;
vec.push_back(temp);
}
for (int i = 0; i < 5; i++) {
b* temp = (b*)&vec[i];
std::cout << temp->d << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
每当您将一个对象推b入Objects的向量vec中时Base,就会创建另一个temp纯粹是type的对象base。您可能会认为(并且您是不对的!)存储在其中的元素vector将是Base类型,但是它将保存一个类型的对象,b但这不是您Dynamic Polymorphism在C ++中的实现方式。
声明:
std::vector<Base> vec; // 1
b temp; // 2
vec.push_back(temp); // 3
Run Code Online (Sandbox Code Playgroud)
第三行将Base通过调用基类的赋值运算符来创建要键入的不同对象Base operator=(const Base& )。
此外,这b* temp = (b*)&vec[i];是未定义的行为,因为您正在明确尝试将指向的对象的指针强制转换base为其派生类类型的b对象,但它不保存类型的对象,b因此,您可能会得到意外的行为。
注意:
使用dynamic_cast在基类和派生类之间进行转换,因为这将确保转换有效。否则,它将返回nullptr。但是,您需要通过至少具有1个虚函数使您的基类多态。
如果转换成功,则dynamic_cast返回类型为new-type的值。如果强制转换失败并且new-type是指针类型,则它将返回该类型的空指针。如果强制转换失败并且new-type是引用类型,则它将引发与std :: bad_cast类型的处理程序匹配的异常。
解:
使用指针矢量进行base分类以实现运行时多态。
std::vector<base *> vec;
for (int i = 0; i < 5; i++) {
b *temp = new b();
vec.push_back(temp);
}
for (int i = 0; i < 5; i++) {
b* temp = dynamic_cast<b *>(vec[i]); // For dynamic cast, you need to add virtual functions to your base class
if (temp != nullptr)
std::cout << temp->d << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
编辑:
对象切片也可以解决您的问题。Object Slicing是这类问题的正确关键词。这是对象切片的定义
对象派生发生在将派生类对象分配给基类对象时,派生类对象的其他属性被切分以形成基类对象。
我在下面的链接中引用了答案之一。有关某些代码段的最佳解释和可能的解决方案,请参见此答案和答案。参见本文,它解释了在基类的向量中推送Derived类的对象时的问题。
在“切片”中,您将派生类的对象分配给基类的实例,从而丢失了部分信息-其中一些信息被“切片”了。
例如,
Run Code Online (Sandbox Code Playgroud)class A { int foo; }; class B : public A { int bar; };因此,类型B的对象具有两个数据成员foo和bar。
然后,如果您要编写此代码:
Run Code Online (Sandbox Code Playgroud)B b; A a = b;然后,b中有关成员栏的信息丢失在a中。