c++对象内存模型之虚析构函数篇(2)

现在讨论第二种情况:

(第一种情况传送门,单独一个类,有虚析构函数,虚函数)

(2)有继承关系,单一继承,父类无虚析构函数,子类有(子类没有就没必要说了)

这种情况让我相当晕,照例先贴代码 :

复制代码
 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A
 5 {
 6        int ia;
 7        public:
 8        A ():ia(15)
 9      {        
10       } 
11      ~A ()
12      {
13            cout << "~A" << endl;
14      } 
15      virtual void f()
16      {
17           cout << "A:f()" <<endl;
18      } 
19 };
20 
21 class B : public A
22 {
23        int ib;
24 public :
25       B():ib(31){}
26       virtual ~B()
27       {
28                  cout << "~B" << endl;           
29       }  
30       virtual void f()
31       {
32                  cout << "B:f()" << endl;           
33       }
34        
35 };
36 
37 typedef void (*F)();
38 
39 int main()
40 {
41 
42      F pf = NULL;
43     B *b = new B();
44     int **p = (int **)b;
45 
46     int flag = 0;
47     pf = (F)p[0][flag];
48     pf();
49 
50     cout << "END"<<p[0][3] << endl;
51     cout << p[1] << endl;
52     cout << p[2] << endl;
53 
54     cout << sizeof(A) << endl;
55     cout << sizeof(B) << endl;
56 }
复制代码

输出如下:

flag = 0;  

1 B:f()
2 END0
3 0xf
4 0x1f
5 8
6 12

flag = 1;

复制代码
1 ~B
2 ~A
3 END4460356
4 0xf
5 0x1f
6 8
7 12
复制代码

flag = 2;

复制代码
~B
~A
END1818846781
0x2c29a0
0x1f
8
12
复制代码

 分析:

flag=0时, B的虚函数f替代了B的虚函数f,打印输出B:f(),这个好理解。要注意的地方是,此时给flag=0,意味着,f在虚函数表的最前面,A没有虚析构函数。END后面的数也很正常。

flag=1时,输出为~B\n~A\n,从现象上来看,是先执行B的析构函数再执行A的析构函数,与常识相符。但END后面的数据与flag=0时的数据0不同,再加上B中的两个成员变量的值是对的,这个让我很难相信对象内存被释放。如果没有释放,END后面的数又很难解释。

flag=2时,输出为~B\n~A\n,成员变量输出已经算是乱码,至少说明内存被释放。ia是乱码,ib仍然是0x1f。从输出上来看,先后执行了B,A的析构函数,确认内存已被释放。由于ib仍是0x1f,我认为是内存没有更新的原因。

结论:与第一篇里说的那样,虚析构函数的第“二”个是释放内存用的,第一个仍然不知道干嘛的。其它的与文章最开始介绍的两个连接里说的一样,子类的虚函数会覆盖父类对应虚函数在虚函数表中的位置。

下面画个内存结构示意图:

A的内存结构请见第一篇文章,这里只画B的。

 vptr是虚函数表的指针,图里的都好说,当然,这些全是根据现象猜的,目前来说没有去看权威资料的原因是为了真正理解,目前看自己能猜对多少。没人给我打分,怕毛。

注:类图可以用ArgoUML,内存图可以用win7自带的画图工具。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值