1. 程式人生 > >C++ 虛擬解構函式

C++ 虛擬解構函式

轉自:http://see.xidian.edu.cn/cpp/biancheng/view/247.html

當派生類的物件從記憶體中撤銷時一般先呼叫派生類的解構函式,然後再呼叫基類的解構函式。但是,如果用new運算子建立了臨時物件,若基類中有解構函式,並且定義了一個指向該基類的指標變數。在程式用帶指標引數的delete運算子撤銷物件時,會發生一個情況:系統會只執行基類的解構函式,而不執行派生類的解構函式。


[例12.3] 基類中有非虛解構函式時的執行情況。為簡化程式,只列出最必要的部分。

 
  1. #include
  2. usingnamespace std;
  3. class
    Point//定義基類Point類
  4. {
  5. public:
  6. Point(){}//Point類建構函式
  7. ~Point(){cout< span>"executing Point destructor"< span>endl;}//Point類解構函式
  8. };
  9. classCircle:public Point //定義派生類Circle類
  10. {
  11. public:
  12. Circle(){}//Circle類建構函式
  13. ~Circle(){cout< span>"executing Circle destructor"< span>endl;}//Circle類解構函式
  14. private:
  15. int radius;
  16. };
  17. intmain()
  18. {
  19. Point *p=new Circle;//用new開闢動態儲存空間
  20. delete p;//用delete釋放動態儲存空間
  21. return 0;
  22. }

這只是一個示意的程式。p是指向基類的指標變數,指向new開闢的動態儲存空間,希望用detele釋放p所指向的空間。但執行結果為:
executing Point destructor

表示只執行了基類Point的解構函式,而沒有執行派生類Circle的解構函式。

如果希望能執行派生類Circle的解構函式,可以將基類的解構函式宣告為虛解構函式,如:
virtual ~Point(){cout< executing Point destructorendl>

程式其他部分不改動,再執行程式,結果為:
executing Circle destructor
executing Point destructor

先呼叫了派生類的解構函式,再呼叫了基類的解構函式,符合人們的願望。

當基類的解構函式為虛擬函式時,無論指標指的是同一類族中的哪一個類物件,系統會採用動態關聯,呼叫相應的解構函式,對該物件進行清理工作。

如果將基類的解構函式宣告為虛擬函式時,由該基類所派生的所有派生類的解構函式也都自動成為虛擬函式,即使派生類的解構函式與基類的解構函式名字不相同。

最好把基類的解構函式宣告為虛擬函式。這將使所有派生類的解構函式自動成為虛擬函式。這樣,如果程式中顯式地用了delete運算子準備刪除一個物件,而delete運算子的操作物件用了指向派生類物件的基類指標,則系統會呼叫相應類的解構函式。

虛解構函式的概念和用法很簡單,但它在面向物件程式設計中卻是很重要的技巧。

專業人員一般都習慣宣告虛解構函式,即使基類並不需要解構函式,也顯式地定義一個函式體為空的虛解構函式,以保證在撤銷動態分配空間時能得到正確的處理。

建構函式不能宣告為虛擬函式。這是因為在執行建構函式時類物件還未完成建立過程,當然談不上函式與類物件的繫結。