首页 > 代码库 > c++对象内存模型之虚析构函数篇(3)
c++对象内存模型之虚析构函数篇(3)
经过前两篇的分析,说实话, 现在的我是比较晕的。但仍然坚持自己的学习方法,先自己“理所当然”的理解,再去求证官方说法。毕竟东西是别人定的,规则是别人的。
1 http://www.cnblogs.com/boota/p/4040310.html2 http://www.cnblogs.com/boota/p/4043282.html
这次是讨论的情形是:有继承关系,单一继承,父类有虚析构函数。(子类有没有虚析构函数不影响,这个结论可以验证,就不另做讨论)
上代码:
1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 int ia; 8 9 A ():ia(15)10 { 11 } 12 virtual ~A ()13 {14 cout << "~A" << endl;15 } 16 virtual void f()17 {18 cout << "A:f()" <<endl;19 } 20 };21 22 class B : public A23 {24 public :25 int ib;26 27 B():ib(31){}28 virtual ~B()29 {30 cout << "~B" << endl; 31 } 32 virtual void f()33 {34 cout << "B:f()" << endl; 35 }36 37 };38 39 typedef void (*F)();40 41 int main()42 {43 44 F pf = NULL;45 B *b = new B();46 int **p = (int **)b;47 48 int flag = 2 ;49 pf = (F)p[0][flag];50 pf();51 52 cout << "END"<<p[0][3] << endl;53 cout << b->ia << endl;54 cout << b->ib << endl;55 56 cout << sizeof(A) << endl;57 cout << sizeof(B) << endl;58 }
程序输出 :
flag=0;
~B~AEND01531812
flag=1;
~B~AEND0406916031812
flag=2;
B:f()END01531812
分析:
说实话,自己在这里真不知道该怎么分析了。于是在程序最后面加了一个delete b,貌似得见云开见明月,貌似。。。
见代码
1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 int ia; 8 9 A ():ia(15)10 { 11 } 12 virtual ~A ()13 {14 cout << "~A" << endl;15 } 16 virtual void f()17 {18 cout << "A:f()" <<endl;19 } 20 };21 22 class B : public A23 {24 public :25 int ib;26 27 B():ib(31){}28 virtual ~B()29 {30 cout << "~B" << endl; 31 } 32 virtual void f()33 {34 cout << "B:f()" << endl; 35 }36 37 };38 39 typedef void (*F)();40 41 int main()42 {43 44 F pf = NULL;45 B *b = new B();46 int **p = (int **)b;47 48 int flag = 2 ;49 pf = (F)p[0][flag];50 pf();51 52 cout << "END"<<p[0][3] << endl;53 cout << b->ia << endl;54 cout << b->ib << endl;55 56 cout << sizeof(A) << endl;57 cout << sizeof(B) << endl;58 delete b;59 }
输出:
flag=0
~B~AEND01531812~A
flag=1
~B~AEND0380701631812[段错误]
调试发现段错误发生在代码的58行,即delete b这句。是不是有点感觉了。
flag=2;
B:f()END01531812~B~A
这下可以写点分析了,不然冏死了。
flag=0时,先执行了虚函数表第一个元素指定的析构函数,对后面的影响是delete语句只执行了A的析构函数,这说明第一个元素是B的析构函数,尼玛,为什么数据ia,ib都没有变???理论上来说,A有虚析构函数,delete b这句是应该输出~B\n~A\n,此时由于先执行了虚函数表中第一个函数,delete只执行了A的析构函数,说明b已经退化成指向A的对象的指针。数据没变,不过数据是合法的,这个可以写个复杂点的类来验证。综上,是不是可以得出第一个析构函数,靠,不知道干嘛的,存疑。
flag=1时,就很正常了。段错误也有了,数据显示不正常,再加上输出也是执行B与A的析构函数的效果,充分说明虚函数表第二个元素就是B的析构函数。这里再猜一次,第一个是A的,或者只是一个效果,表明是A的子类,so还是不知道干嘛的。
flag=2时,这里就皆大欢喜了。没什么可说的。
所以,我们的结论就在这里停住了,貌似三个代码都表明,虚析构函数的第二个是本类的析构函数,其它等我再写个复杂点的代码,中间有指针申请空间的那种,这个在栈里玩的代码,估计是很难引起段错误。
照例内存图示画一个,如下:
c++对象内存模型之虚析构函数篇(3)