gpt4 book ai didi

c++ - 为什么这段代码不将基类转换为 C++ 中的派生类?

转载 作者:行者123 更新时间:2023-12-01 19:54:43 25 4
gpt4 key购买 nike

为什么这段 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;
}

最佳答案

每当将 b 对象插入 Base 对象的 vector vec 时,都会从 temp 创建另一个对象> 纯粹是base 类型。您可能会认为(您错了!)存储在 vector 中的元素将是 Base 类型,但它将保存一个 b 类型的对象,但是这不是在 C++ 中实现动态多态性的方式。

声明:

std::vector<Base> vec; // 1
b temp; // 2
vec.push_back(temp); // 3

第三行将通过调用基类Base operator=(const Base& )的赋值运算符来创建一个不同的对象来类型Base

此外,b* temp = (b*)&vec[i]; 是一种未定义的行为,因为您显式尝试将指向 base 对象的指针转换为它是派生类类型 b 但它不包含类型 b 的对象,因此,您可能会得到意外的行为。

注意:

使用dynamic_cast用于在基类和派生类之间进行转换,因为它将确保转换有效。否则,它将返回nullptr。但是,您需要通过至少具有 1 virtual function 来使基类具有多态性。 .

If the cast is successful, dynamic_cast returns a value of type new-type. If the cast fails and new-type is a pointer type, it returns a null pointer of that type. If the cast fails and new-type is a reference type, it throws an exception that matches a handler of type std::bad_cast.

解决方案:

使用指向类的指针 vector 来实现运行时多态性。

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;
}

编辑:

对象切片也是您问题的解决方案对象切片是解决此类问题的正确关键字。这是definition对象切片的原理

Object slicing happens when a derived class object is assigned to a base class object, additional attributes of a derived class object are sliced off to form the base class object.

我引用link中的答案之一以下。看这个answeranswer通过一些代码片段获得最佳解释和可能的解决方案。看这个article ,它解释了将派生类的对象插入基类的 vector 时出现的问题。

"Slicing" is where you assign an object of a derived class to an instance of a base class, thereby losing part of the information - some of it is "sliced" away.

For example,

class A {
int foo;
};

class B : public A {
int bar;
};

So an object of type B has two data members, foo and bar.

Then if you were to write this:

B b;
A a = b;

Then the information in b about member bar is lost in a.

关于c++ - 为什么这段代码不将基类转换为 C++ 中的派生类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59026246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com