我是下面的结构。我最小化到尽可能短的方式来重现错误:
我有两个级别的派生类。我没有任何编译错误。错误出现在运行时:
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)
push_back基derivedB类指针时,您存储了一个悬空指针。
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这些方法并不是严格必要的,但在阅读代码时会有所帮助 - 如果您认为您重写了某些内容,但实际上没有重写,它还会给您一个编译错误。