经过前两篇的分析,说实话, 现在的我是比较晕的。但仍然坚持自己的学习方法,先自己“理所当然”的理解,再去求证官方说法。毕竟东西是别人定的,规则是别人的。
1 http://www.cnblogs.com/boota/p/4040310.html 2 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 A 23 { 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
~A
END0
15
31
8
12
flag=1;
~B
~A
END0
4069160
31
8
12
flag=2;
B:f()
END0
15
31
8
12
分析:
说实话,自己在这里真不知道该怎么分析了。于是在程序最后面加了一个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 A 23 { 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
~A
END0
15
31
8
12
~A
flag=1
~B
~A
END0
3807016
31
8
12
[段错误]
调试发现段错误发生在代码的58行,即delete b这句。是不是有点感觉了。
flag=2;
B:f()
END0
15
31
8
12
~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时,这里就皆大欢喜了。没什么可说的。
所以,我们的结论就在这里停住了,貌似三个代码都表明,虚析构函数的第二个是本类的析构函数,其它等我再写个复杂点的代码,中间有指针申请空间的那种,这个在栈里玩的代码,估计是很难引起段错误。
照例内存图示画一个,如下: