【日常】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 關鍵字!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM