c++之——虛析構函數

先看代碼:ios

 1 #include<iostream>
 2 using namespace std;  3 
 4 class Parent {  5 public:  6     Parent() :a(100), b(200), c(300)  7  {  8         
 9         p = new char[10];  10         //strcpy(p, "abc");
 11         cout << "parent 無參構造。。。\n";  12  }  13     Parent(int test) :a(1000), b(2000), c(3000)  14  {  15         p = new char[10];  16         //strcpy(p, "abc");
 17         cout << "parent 有參構造。。。\n";  18  }  19     ~Parent()  20  {  21         delete[] p;  22         cout << "Parent 析構。。。\n";  23  }  24     int a;  25     int b;  26     int c;  27     char *p;  28     void p_print()  29  {  30         cout << "a b c is" << a << " " << b << " " << c << endl;  31  }  32 
 33 };  34 class Child1 :  public Parent  35 {  36 public:  37     Child1() :Parent(1),a(10), b(0), c(0)  38  {  39         p = new char[10];  40     // strcpy(p, "abc");
 41         cout << "child1 構造\n";  42  }  43     ~Child1()  44  {  45         delete[] p;  46         cout << "child1 析構,,,\n";  47  }  48     void c1_print()  49  {  50         cout << "a b c is" << a << " " << b << " " << c << endl;  51  }  52 
 53     int a;  54     int b;  55     int c;  56     char *p;  57 };  58 class Child2 :  public Child1  59 {  60 public:  61     Child2() :Child1(), b(2), c(3)  62  {  63         p = new char[10];  64         //strcpy(p, "abc");
 65         cout << "child2 構造\n";  66  }  67     ~Child2()  68  {  69         delete[] p;  70         cout << "child2 析構,,,\n";  71  }  72     void c2_print()  73  {  74         cout << "a b c is" << Parent::a << " " << b << " " << c << endl;  75  }  76     //int a;
 77     int b;  78     int c;  79     char *p;  80 };  81 /*
 82 class Child3 : public Child1, public Child2  83 {  84 public:  85  Child3() : Child1(), Child2(), b(20), c(30) { cout << "child 構造\n"; }  86  ~Child3()  87  {  88  cout << "child 析構,,,\n";  89  }  90  void c3_print()  91  {  92  cout << "a b c is" << a << " " << b << " " << c << endl;  93  }  94  //int a;  95  int b;  96  int c;  97 };  98 */
 99 void play() 100 { 101     Child2* c2 = new Child2; 102     delete c2; 103 } 104 int main() 105 { 106     //Child2* c2 = new Child2;
107  play(); 108     return 0; 109 }

這樣是沒問題的(c++編譯器會以構造相反的順序執行析構函數),可是,在不少時候,咱們不能在調用函數末尾就delete掉這個內存,還須要和後續交互。好比做爲函數參數,爲了實現多態,咱們函數參數是父類的指針,因此更常見和通常的設計思惟是更改paly和main函數以下:c++

 1 void play(Parent* p)  2 {  3     delete p;  4 }  5 int main()  6 {  7     Child2* c2 = new Child2;  8  play(c2);  9     return 0; 10 }

運行結果顯示內存泄漏了,只析構了父類;因此咱們有那麼一種需求,要想和多態的效果同樣,傳什麼指針去,自動析構應該析構的東西,更改代碼,實現虛析構函數。函數

只用更改基類的析構函數,加上virtual關鍵字:spa

1     virtual ~Parent() 2  { 3         delete[] p; 4         cout << "Parent 析構。。。\n"; 5     }

這樣就沒有內存泄漏了。設計

知識簡要:指針

 若是基類的析構函數不是虛函數,則delete一個指向派生類對象的基類指針將產生未定義的行爲。以前咱們介紹過一個準則,若是一個類須要析構函數,那麼它一樣須要拷貝和賦值操做。基類的析構函數並不遵循上述準則,它是一個重要的例外。code

相關文章
相關標籤/搜索