程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 析構函數的奧秘

析構函數的奧秘

編輯:關於C++

請看如下一段代碼:

class A {
public:
A () { pValue = new int[100]; printf("Constructor of A\n"); }
~A () { delete [] pValue; printf("Deconstructor of A\n"); }
private:
int * pValue;
};

class B {
public:
~B () { printf("Deconstructor of B\n"); }
};

class C : public B {
public:
~C () { printf("Deconstructor of C\n"); }
private:
A a;
};
int main(int argc, char* argv[])
{
C c;
return 0;
}

類C從類B中繼承出來,類C中聚合了一個類A的對象,類C的析構函數並未調用類A的析構函數,請問:這段代碼執行後,會調用類A的析構函數釋放內存嗎?經測試,執行結果如下:

Constructor of A
Deconstructor of C
Deconstructor of A
Deconstructor of B

由此可以看出,C的析構函數確實調用了類A的析構函數,該調用是由編譯器隱含加入的,隨後還調用了基類B的析構函數,但是請注意,編譯器只會為基類和聚合類添加對析構函數的調用,如果C中的成員為指向類A的指針,則編譯器不會加入對類A的析構函數的調用。

那麼,如果我們把main函數改變一下:

int main(int argc, char* argv[])
{
B * b = new C;
delete b;
return 0;
}

請問:這段代碼會發生內存洩漏嗎?執行結果如下:

Constructor of A
Deconstructor of B

發生了什麼?調用了A的構成函數分配了內存,卻只調用了B的析構函數,C和A的析構函數都沒有調用,內存沒有釋放,為什麼?

有人也許已經看出了問題所在,B和C的析構函數都應該是虛函數,否則,由於b的類型為指向類B的指針,delete b只會調用B的析構函數。當B和C的析構函數都是虛函數時,編譯器會根據b指向的對象實際上是C的對象,而去調用C的析構函數。請對代碼作如下改變:

class B {
public:
virtual ~B () { printf("Deconstructor of B\n"); }
};
class C : public B {
public:
virtual ~C () { printf("Deconstructor of C\n"); }
private:
A a;
};

再次運行,結果正確:

Constructor of A
Deconstructor of C
Deconstructor of A
Deconstructor of B

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved