2016-09-20 45 views
0
#include <iostream> 
using namesapce std; 
class A 
{ 
    public: 
     virtual ~A(){cout<<"delete A"<<endl}; 
}; 
class B: public A 
{ 
    public: 
     B(int n):n(n){} 
     void show(){cout<<n<<endl;} 
     ~B(){cout<<"delete B"<<endl;} 
    private: 
     int n; 

} 
int main() 
{ 
    A *pa; 
    B *pb = new B(1); 
    pa = pb; 
    delete pa; 
    pb->show(); 
    return 0; 
} 

当CALSS A的析构函数是virtual ~A(){...},程序的输出: delete B delete A 1 当类A的析构函数是~A(){...},progarm的输出: delete A 0 为什么n的值是不同的时,类A的析构函数是虚拟非虚拟?当调用B的析构函数销毁对象时,为什么会话成员n仍然存在?当A类的析构函数是虚拟的还是非虚拟的时,为什么B的calss成员n有不同的值?

+0

你明白虚拟函数是什么吗? – Barry

+1

什么是'pb-> show(){};'? – AnT

+0

你可能想阅读这个http://www.learncpp.com/cpp-tutorial/122-virtual-functions/ –

回答

1
A *pa; 
B *pb = new B(1); 
pa = pb; 

这就是所谓的上传。每当向上转换完成时,基类的析构函数应该是虚拟的。

没有虚拟基本的析构函数,删除pa将只调用不希望的基类析构函数,因为它的派生类对象永远不会被销毁并导致内存泄漏。

基类的虚析构函数会调用第一个派生类的析构函数,然后它会破坏自己,这是期望的行为,并且不会因为上传而导致任何泄漏。

+0

简而言之,如果没有虚拟基类析构函数,你会得到_undefined behavior_。 – qxz

+0

为什么n的价值不同? – PengWin

+0

waht是未定义的行为,为什么编译器告诉编码器有错误? – PengWin

1

您的程序展示未定义的行为。这是你“为什么”问题的唯一答案。

首先,如果析构函数A不是虚拟的,那么在你的代码中做delete pa会导致未定义的行为。试图以delete类型B的对象通过指向父类型A *的指针导致未定义的A析构函数的行为不是虚拟的。

其次,pb->show()似乎是试图调用一个已经被破坏的对象的方法。行为也是未定义的,无论析构函数是否为虚拟的。

相关问题