gpt4 book ai didi

c++ - 检查基类对象的子类 - 继承

转载 作者:搜寻专家 更新时间:2023-10-31 00:52:48 24 4
gpt4 key购买 nike

我需要在执行时知道我正在使用的基类对象的子类型。

首先,我有一个名为 Element 的基类。然后,我有几个名为 CarAdult... 的子类,它们都派生自 Element。在我的代码的某些部分,我创建了一些我存储在 Element 数组中的类型的对象。

当我遍历数组并尝试恢复对象的主要类型时,问题就来了。

我一直在尝试使用 dynamic_cast 来做到这一点,但每个 Element 都可以成功地转换为 CarAdult,或其他...

这是代码:

Element elements[3];
Car c;
Adult a1;
Adult a2;
elements[0] = c;
elements[1] = a1;
elements[2] = a2;
int numElements = 3;
for(int i = 0; i< numElements; i++){
if(dynamic_cast<Adult*>(&elements[i]) == nullptr){
cout << "Its an adult" << endl;
}else{
cout << "Sth else" << endl;
}
}

这就是结果:

Its an adult
Its an adult
Its an adult

这是子类代码:

class Car : public Element{
...
};

class Adult : public Element{
...
};

最佳答案

您的代码有两个问题。

一个Element elements[3];创建一个Element对象数组。不是“派生自 Element 的类的对象”。您不能在这样的数组中存储除 Element 以外的任何内容,任何这样做的尝试都会导致 object slicing。 : 源对象的非 Element 部分被切掉(丢弃),只有 Element 部分进入。

如果要动态多态,就得用指针或者引用,通常还要动态分配。在您的情况下,这可能看起来像这样:

std::unique_ptr<Element> elements[3];
Car c;
Adult a1;
Adult a2;
elements[0] = std::make_unique<Car>(c);
elements[1] = std::make_unique<Adult>(a1);
elements[2] = std::make_uniuqe<Adult>(a2);

或者,如果您想避免复制对象:

std::unique_ptr<Element> elements[3];
auto c = std::make_unique<Car>();
auto a1 = std::make_unique<Adult>();
auto a2 = std::make_unique<Adult>();
elements[0] = std::move(c);
elements[1] = std::move(a1);
elements[2] = std::move(a2);

或者直接在数组中创建它们:

std::unique_ptr<Element> elements[3];
elements[0] = std::make_unique<Car>();
elements[1] = std::make_unique<Adult>();
elements[2] = std::make_unique<Adult>();

第二,您误解了dynamic_cast 的结果。如果 dynamic_cast 成功,它返回转换为适当类型的指针。如果失败,它返回一个空指针。您的情况是相反的,因为您将 == nullptr 解释为成功。循环实际上应该是这样的(使用第 1 点的 unique_ptr):

for(int i = 0; i< numElements; i++){
if(dynamic_cast<Adult*>(elements[i].get())){
cout << "Its an adult" << endl;
}else{
cout << "Sth else" << endl;
}
}

一些旁注:

  • 由于您的 Element 用作多态基类,因此它应该有一个虚拟析构函数。否则,使用 Element 类型的指针删除派生自 Element 类型的动态分配对象将导致未定义行为(很可能是内存损坏)。

  • 如果您的 Element 只是作为一个抽象基础,并且您从不期望类型完全是 Element 的对象(不是从它派生的)存在,您应该通过给 Element 至少一个纯虚函数 (virtual void foo() = 0;) 使它抽象。如果它是一个真正的基类,它可能自然会包含一些候选者。

  • 在使用基类时需要知道确切的派生类型通常是糟糕设计的标志。理想情况下,Element 应包含虚函数,涵盖您可能需要以类型抽象方式对对象执行的所有功能。当然,也存在异常(exception)情况,但您可能应该重新评估您的设计,以确保那些 dynamic_casts 确实是必需的。

关于c++ - 检查基类对象的子类 - 继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50668741/

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