【发布时间】:2017-07-29 09:00:36
【问题描述】:
假设我们有以下类层次结构:
class B{
B() { cout<<"B\n"; }
~B(){ cout<<"~B\n"; }
};
class D1 : virtual public B {
D1() { cout<<"D1\n"; }
~D1(){ cout<<"~D1\n"; }
};
class D2 : virtual public B {
D2() { cout<<"D2\n"; }
~D2(){ cout<<"~D2\n"; }
};
class MM : public D1, public D2 {
MM() { cout<<"MM\n"; }
~MM(){ cout<<"~MM\n"; }
};
int main(){
B *p = new MM();
D1 *p2 = dynamic_cast<D1*>(p);
D2 *p3 = dynamic_cast<D2*>(p);
MM *p4 = dynamic_cast<MM*>(p);
//delete p4;
//delete p3;
delete p2;
delete p;
return 0;
}
我不太习惯 dynamic_cast 和从基类到派生类的指针,所以如果我错了,请纠正我,但这基本上会创建一个 B* 类型的指针,指向一个 MM() 类型的对象。此后,它创建另外两个指针,并使用 dynamic_cast 将 B* 指针转换为 D*、D2* 和 MM*。
现在让我担心的是:所有四个都指向同一个内存块(对吗?)。当我们删除 p2,然后删除 p 时,它工作正常。如果我们取消注释“delete p3”或删除“p4”,程序就会崩溃,我不知道为什么。我还观察到,如果我们取消注释前面提到的任何一个删除语句并注释“删除 p2”,代码就可以正常工作。
有人可以解释一下吗?谢谢!
PS:你们中的任何人都可以解释一下,一旦我们创建另一个指针并将前一个指针与 dynamic_cast 一起使用,分配的内存会发生什么?谢谢!
【问题讨论】:
-
为什么要这样做?你应该有虚拟析构函数
-
不假思索... 一个
new和多个delete绝对是一个错误。顺便说一句,只有在B中至少有一个virtual函数时,代码才应该编译。你应该使用虚拟析构函数 -
请在删除任何内容之前使用调试器并打印指针的值。您的演员表无效,因此指针(不包括 p)应该为空。
-
@patatahooligan 删除 null 是个问题,所以这不是崩溃的原因
-
必须对其进行调试和进一步调查,因为它不应该在那里崩溃。