?
这种情况让我相当晕,照例先贴代码 :
?
复制代码
?1 #include
?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()" <
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"<
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,我认为是内存没有更新的原因。
?
结论:与第一篇里说的那样,虚析构函数的第“二”个是释放内存用的,第一个仍然不知道干嘛的。其它的与文章最开始介绍的两个连接里说的一样,子类的虚函数会覆盖父类对应虚函数在虚函数表中的位置。