派生类中的不良向下转型

H'H*_*H'H 1 c++

我是下面的结构。我最小化到尽可能短的方式来重现错误:

我有两个级别的派生类。我没有任何编译错误。错误出现在运行时:

base.exe 中 0x00007FFF1021CF19 处出现未处理的异常:Microsoft C++ 异常:内存位置 0x00000022B9BDF458 处的 std::__non_rtti_object。

有什么建议吗?

#include <iostream>
#include <vector>
#include <memory>

class Base {
public:
    int a;
    Base(int _a) : a(_a) {};
    virtual void print() = 0;
};

class derivedA : public Base
{
public:
    derivedA(int _a) : Base(_a) {};
    void print() { std::cout << "dA" << std::endl; }
};

class derivedB : public derivedA
{
public:
    derivedB(int _a) : derivedA(_a) {};
    void print() { std::cout << "dB" << std::endl; }
};

void construct(std::vector<derivedA*>& da_vec) {
    da_vec.push_back(std::unique_ptr<derivedA>(new derivedB(4)).get());
}

void func(derivedA& da)
{
    derivedB& db = dynamic_cast<derivedB&>(da);
    db.print();
}

int main()
{
    std::vector<derivedA*> da_vec;
    construct(da_vec);
    for (auto& da : da_vec)
        func(*da);
}
Run Code Online (Sandbox Code Playgroud)

Ted*_*gmo 5

  • 当您使用push_backderivedB类指针时,您存储了一个悬空指针。
    da_vec.push_back(std::unique_ptr<derivedA>(new derivedB(4)).get());
    
    Run Code Online (Sandbox Code Playgroud)unique_ptr<derivedA>在表达式末尾被销毁,因此您从中获得的指针 是.get()“悬空”的,这意味着它不应该被取消引用。它所指的物体已经消失了。

为了解决这个问题,我建议您将其存储std::unique_ptr<derivedA>在您的vector. 您也不需要derivedB&在调用重写的print方法之前进行强制转换。这就是多态性自动为您解决的问题。

例子:

da_vec.push_back(std::unique_ptr<derivedA>(new derivedB(4)).get());
Run Code Online (Sandbox Code Playgroud)

演示

注意:我也创建了Base析构函数virtual,这是为了通过基类指针销毁对象以便调用所有析构函数(从最派生到基类)所必需的。

我还标记了重写的方法,override这些方法并不是严格必要的,但在阅读代码时会有所帮助 - 如果您认为您重写了某些内容,但实际上没有重写,它还会给您一个编译错误。