This question already has answers here:
When to use virtual destructors?
(17个答案)
2年前关闭。
我花了几个小时试图弄清楚问题出在哪里,但似乎太奇怪了。
我用一种更容易理解的方式重写了我的问题。
当到达说删除的行时,debbug会产生一个断点。
附言值得一提的是,如果我们将int b1移到Base2上,它将可以正常工作。
Base1:
Base2.h:
Base2.cpp:
衍生的:
主要的:
(17个答案)
2年前关闭。
我花了几个小时试图弄清楚问题出在哪里,但似乎太奇怪了。
我用一种更容易理解的方式重写了我的问题。
当到达说删除的行时,debbug会产生一个断点。
附言值得一提的是,如果我们将int b1移到Base2上,它将可以正常工作。
Base1:
#pragma once
class Base1
{
public:
Base1();
~Base1();
int b1;
};
Base2.h:
#pragma once
#include <iostream>
#include <vector>
class Derived;
class Base2
{
public:
Base2();
~Base2();
std::vector <std::vector <Base2*>> vec;
void doSomething(Derived& d);
};
Base2.cpp:
#include "Base2.h"
#include "Derived.h"
Base2::Base2()
{
//the numbers 1 and 5 does not really metter
vec.resize(1);
vec[0].resize(5);
}
Base2::~Base2()
{
}
void Base2::doSomething(Derived& d)
{
vec[0][d.b1] = new Derived();
delete vec[0][d.b1];
}
衍生的:
#pragma once
#include "Base1.h"
#include "Base2.h"
class Derived : public Base1, public Base2
{
public:
Derived();
~Derived();
};
主要的:
#include <iostream>
#include "Derived.h"
int main()
{
Derived d;
d.b1 = 1;
d.doSomething(d);
}
最佳答案
Base2
缺少虚拟析构函数。
通过指向基础对象的指针删除派生对象,如果该基础对象没有虚拟析构函数,则会导致未定义的行为。
通常,这种UB仅导致丢失析构函数调用(并因此导致内存/资源泄漏),但是在这种情况下,由于涉及多个继承,因此情况有所不同。
将new Derived()
返回的指针转换为Base2 *
时,指针的数值会更改(由于多重继承)。
在delete
调用~Base2()
之后,它随后将指针传递给内存释放函数。
释放函数期望使用与new
返回的地址相同的地址,该地址是整个Derived
实例的地址。取而代之的是,它获得了Base2
子对象的地址,该地址是不同的(同样,由于多重继承)。
这与其他任何“没有通过delete
返回的指针使用new
”情况没有什么不同,通常会导致崩溃。
如果Base2
具有虚拟析构函数,则将在释放之前将指针调整为指向Derived
的整个实例。