【日常】C++ 的那些“坑” —— delete 与 析构函数 与 virtual 的 9 个小例子

C++中有无数的坑,但毕竟……

今天就踩到了,也算是基本问题了,记录一下,顺便以后可以考考自己。你也可以猜猜答案,大牛绕行。

0x1 先看这个:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     Bpp* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果:

~Bpp

~App
请按任意键继续. . .

0x02 : 再来 ,改了第32行

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     App* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果:

~App
请按任意键继续. . .

0x03 下一个 改动 7 line

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     virtual ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     App* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果:

~Bpp

~App
请按任意键继续. . .

0x04 next 改动 line 20

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     virtual ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     virtual ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     App* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果和 0x03一样:

~Bpp

~App
请按任意键继续. . .

0x05 接着 再在第7 行中 去掉 virtual

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     virtual ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     App* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果:

在33行,程序报错,崩溃。

0x6 改动 32行:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     virtual ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     void* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果:执行成功。

请按任意键继续. . .

0x07 把所有 virtual 去掉

#include <stdio.h>
#include <stdlib.h>

class App
{
public:
    ~App()
    {
        printf("\n~App\n");
    }
    void output()
    {
        printf("A");
    }
};

class Bpp : public App
{
public:
    ~Bpp()
    {
        printf("\n~Bpp\n");
    }
    void output()
    {
        printf("B");
    }
};

int main(char args[]) 
{
    void* b = new Bpp();
    delete b;

    system("pause");
    return 0;
}

结果:

请按任意键继续. . .

0x08 加上所有 virtual :

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     virtual ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     virtual ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     void* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果:

请按任意键继续. . .

 

0x09 最后:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 class App
 5 {
 6 public:
 7     ~App()
 8     {
 9         printf("\n~App\n");
10     }
11     void output()
12     {
13         printf("A");
14     }
15 };
16 
17 class Bpp : public App
18 {
19 public:
20     virtual ~Bpp()
21     {
22         printf("\n~Bpp\n");
23     }
24     void output()
25     {
26         printf("B");
27     }
28 };
29 
30 int main(char args[]) 
31 {
32     Bpp* b = new Bpp();
33     delete b;
34 
35     system("pause");
36     return 0;
37 }

结果,可以猜猜:

1 ~Bpp
2 
3 ~App
4 请按任意键继续. . .
最后的答案

 

结语:

1. 通常应该给基类提供一个虚析构函数,即使它不需要析构函数 —— 《C++ Primer Plus (第6版)中文版》, 505页

2. 如果一个类带有任何 virtual 函数,这个类就应该拥有 virtual 析构函数 —— 《Effective C++ 中文版,第三版》,条款07:为多态基类声明 virtual 析构函数,44页

3. 如果一个类被当作基类(也就是说这个类需要被其他类继承),那这个类的析构函数就要加上 virual 关键字!

posted @ 2017-04-28 13:09  endlesstravel  阅读(2234)  评论(2编辑  收藏  举报