基类虚析构函数分析

本文探讨了C++中多态的实现机制,特别是通过虚函数表实现动态绑定的过程。文中详细解释了为何将基类的析构函数声明为虚函数的重要性,以及如何避免由此引发的内存泄漏问题。

  多态是由虚函数表来实现,通过父类指针来实现动态绑定。子类重写父类的虚函数后,覆盖虚函数表中父类该虚函数在表中原来的位置,也许“覆盖”也就是由此得称。 

   那析构函数是否也如此呢?程序代码中经常可以见到将基类的析构函数写成虚函数,目的就是为了防止由以下这种情况造成的内存泄漏: 

      class A;

      class B : public A{};

      ......

  B *b = new B();

      A *p = (A*)b;

      delete p;     

  此时系统仅调用了A的析构函数,并没有调用B的析构函数,为什么呢?指针p指向的是B的对象啊!  

  而且,为什么将A的析构函数写成虚函数,通过A类指针来delete就能调用析构B呢?难道又是动态绑定?可是,动态绑定的前提是两个函数要有一致的声明啊,这里就算是~A();是virtual的,那也不能说会动态绑定到~B();去啊,起码它们不是同名的。

  打开VC调试后,在watch窗口查看后得知,指针p和b的值一样,可是把“+”展开后看到的却不一样,p展开后竟然没有看到B的成员变量,由此猜测:这样的话,那类B独有的函数也同样不能调用了(废话,谁这么用过)。那也就是说,通过指针p来delete,调用的当然也是A的析构函数了,难怪B的析构函数没被调用。

  A析构写成虚函数后发现,B对象的虚函数表里(展开指针p的“+”后)就出现了B的析构函数相关信息,它覆盖了原来A的虚析构函数,也只能覆盖(怎么覆盖?这个......),否则通过基类指针不知要调用哪个函数(这么猜不知对不对)。然后根据析构的顺序,再调用A的析构函数。

  还有一个问题,为什么指针b转化为A类指针后,类B独有的成员会不见呢,而且,虚函数表指针也是类B独有的,为什么它就还能留在那儿。这得从C++的对象内存模型说起brabra...,估计应该跟截断技术有关,从派生层次上看(通过基类派生类的构造顺序看),构造一个派生类对象时,先构造父类的成员变量,然后......而C++为类对象结构的头四个字节初始化为虚函数表指针(从单继承的角度),所以,截断的时候仍然保留了(呵呵,是这样吧)。

  望各位走过路过,有什么纠正的地方,不吝赐教。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值