C++解析(15):二階構造模式
阿新 • • 發佈:2018-12-07
0.目錄
1.建構函式與半成品物件
2.二階構造
3.小結
1.建構函式與半成品物件
關於建構函式:
- 類的建構函式用於物件的初始化
- 建構函式與類同名並且沒有返回值
- 建構函式在物件定義時自動被呼叫
問題:
- 如何判斷建構函式的執行結果?
- 在建構函式中執行return語句會發生什麼?
- 建構函式執行結束是否意味著物件構造成功?
(沒有辦法判斷建構函式的執行結果,建構函式執行結束不意味著物件構造成功)
用一個狀態來表示物件是否構造成功:
#include <stdio.h> class Test { int mi; int mj; bool mStatus; public: Test(int i, int j) : mStatus(false) { mi = i; return; mj = j; mStatus = true; } int getI() { return mi; } int getJ() { return mj; } int status() { return mStatus; } }; int main() { Test t1(1, 2); if( t1.status() ) { printf("t1.mi = %d\n", t1.getI()); printf("t1.mj = %d\n", t1.getJ()); } return 0; }
輸出結果為空。
建構函式:
- 只提供自動初始化成員變數的機會
- 不能保證初始化邏輯一定成功
- 執行return語句後建構函式立即結束
建構函式能決定的只是物件的初始狀態,而不是物件的誕生!!
半成品物件的概念:
- 初始化操作不能按照預期完成而得到的物件
- 半成品物件是合法的C++物件,也是Bug的重要來源
2.二階構造
工程開發中的構造過程可分為:
- 資源無關的初始化操作
- 不可能出現異常情況的操作
- 需要使用系統資源的操作
- 可能出現異常情況,如:記憶體申請,訪問檔案
二階構造:
二階構造示例一:
二階構造示例二:
示例程式碼:
#include <stdio.h> class TwoPhaseCons { private: TwoPhaseCons() // 第一階段建構函式 { } bool construct() // 第二階段建構函式 { return true; } public: static TwoPhaseCons* NewInstance(); // 物件建立函式 }; TwoPhaseCons* TwoPhaseCons::NewInstance() { TwoPhaseCons* ret = new TwoPhaseCons(); // 若第二階段構造失敗,返回 NULL if( !(ret && ret->construct()) ) { delete ret; ret = NULL; } return ret; } int main() { TwoPhaseCons* obj = TwoPhaseCons::NewInstance(); printf("obj = %p\n", obj); delete obj; return 0; }
執行結果為:
[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out
obj = 0xd4f010
若是二階構造失敗了呢?
#include <stdio.h>
class TwoPhaseCons
{
private:
TwoPhaseCons() // 第一階段建構函式
{
}
bool construct() // 第二階段建構函式
{
return false;
}
public:
static TwoPhaseCons* NewInstance(); // 物件建立函式
};
TwoPhaseCons* TwoPhaseCons::NewInstance()
{
TwoPhaseCons* ret = new TwoPhaseCons();
// 若第二階段構造失敗,返回 NULL
if( !(ret && ret->construct()) )
{
delete ret;
ret = NULL;
}
return ret;
}
int main()
{
TwoPhaseCons* obj = TwoPhaseCons::NewInstance();
printf("obj = %p\n", obj);
delete obj;
return 0;
}
執行結果為:
[[email protected] Desktop]# g++ test.cpp
[[email protected] Desktop]# ./a.out
obj = (nil)
會返回一個空。
使用二階構造模式後,物件只能在堆空間上建立,不能在棧上產生了。這恰恰是工程裡面最重要的一個決定,因為在工程中,物件往往是比較巨大的,不適合放在棧空間當中,都應該放到堆空間裡面去。
3.小結
- 建構函式只能決定物件的初始化狀態
- 建構函式中初始化操作的失敗不影響物件的誕生
- 初始化不完全的半成品物件是Bug的重要來源
- 二階構造人為的將初始化過程分為兩部分
- 二階構造能夠確保建立的物件都是完整初始化的