有人認為構造函數中不應使用 this 指針,因為對象「尚未完全形成」。實則不然,只要謹慎,在函數體與初始化列表中均可安全使用 this。因為「未完全形成」不等於「什麼都沒有」。
進入構造函數(及其鏈式調用)前,編譯器已完成:
構造函數體(或其調用的函數)能 可靠訪問:
原因:這些成員在構造函數體開始執行時已完整建立。
構造函數體(或其調用的函數)不能 向下調用被派生類重定義的虛函數。因為在基類構造期間,「對象還不是一個派生類對象」。
this)。優秀的 OO 設計強調「高內聚」,產生許多單一職責的小對象。小對象間的協作需配置(如 Observer 模式中 subject.RegisterObserver(observer),DirectShow 中 filterGraph.SetVideoWindow(videoWindow))。構造函數正是典型的配置時機:
class CMyWindow : public CWnd {
private:
CFilterGraph filterGraph;
public:
CMyWindow() { filterGraph.SetVideoWindow(this); } // 此處安全使用 this
};
| 表一:誰被調用 | 普通函數 | 構造函數 | 析構函數 |
|---|---|---|---|
| 調用順序 | class::fun() | superclass::superclass() → subclass::subclass() | subclass::~subclass() → superclass::~superclass() |
| 表二:虛函數在哪裡被調用 | 非虛函數 | 虛函數 |
|---|---|---|
| 普通函數 | class::fun() | obj.vfun() |
| 構造函數 | class::fun() | class::vfun() (靜態綁定) |
| 析構函數 | class::fun() | class::vfun() (靜態綁定) |
關鍵認知: 「構造/析構/普通」與「虛/非虛」是完全獨立的分類維度:
obj.vfun()」虛析構函數示例:
class superclass { virtual ~superclass() { println("superclass::~superclass()") }; };
class subclass : public superclass { virtual ~subclass() { println("subclass::~subclass()") }; };
superclass* super = new subclass();
delete super; // 輸出:subclass::~subclass() → superclass::~superclass()
執行 delete super 時:是串聯調用(因是析構函數),從 subclass::~subclass() 開始(因實際對象類型是 subclass)。