【C++深度剖析教程4】C++的二阶构造模式
今天學(xué)習(xí)的是C++中的二階構(gòu)造模式,二階構(gòu)造模式只是設(shè)計模式中的簡單的模式,是一種軟件設(shè)計的方法,并沒有我們想象的那么高深,設(shè)計模式也是一樣,只不過是一系列的設(shè)計方法,只要我們懂得了原理,那么一切都是相通的。
回顧:構(gòu)造函數(shù)的回顧
關(guān)于構(gòu)造函數(shù):
- 類的構(gòu)造函數(shù)用于對象的初始化
- 構(gòu)造函數(shù)與類同名并且沒有返回值
- 構(gòu)造函數(shù)在對象定義時自動被調(diào)用
問題:
1.如何判斷構(gòu)造函數(shù)的執(zhí)行結(jié)果?
2.在構(gòu)造函數(shù)中執(zhí)行return語句會發(fā)生什么?
3.構(gòu)造函數(shù)執(zhí)行結(jié)束是否意味著對象構(gòu)造成功?
下面我們以碼實例來分析問題:
#include <stdio.h>class Test {int mi;int mj; public:Test(int i, int j){mi = i;mj = j;}int getI(){return mi;}int getJ(){return mj;} };int main() { Test t1(1, 2);printf("t1.mi = %d\n", t1.getI());printf("t1.mj = %d\n", t1.getJ());return 0; }這就是一個普普通通的代碼,用來初始化兩個變量的。編譯輸出結(jié)果為:
t1.mi = 1 t1.mj = 2現(xiàn)在我在構(gòu)造函數(shù)中加一個return語句如下:
#include <stdio.h>class Test {int mi;int mj; public:Test(int i, int j){mi = i;return;mj = j;}int getI(){return mi;}int getJ(){return mj;} };int main() { Test t1(1, 2);printf("t1.mi = %d\n", t1.getI());printf("t1.mj = %d\n", t1.getJ());return 0; }執(zhí)行結(jié)果為:
t1.mi = 1 t1.mj = 2527220很顯然mj變成了一個隨機數(shù),那么說明構(gòu)造函數(shù)在構(gòu)造對象t1時,執(zhí)行到return語句后就返回了,并沒有繼續(xù)執(zhí)行,那么到底是不是這樣的呢?我們來做一個試驗就知道了,添加一個bool型變量來判斷構(gòu)造函數(shù)執(zhí)行到哪里去了,代碼如下:
#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; }編譯執(zhí)行后,沒有輸出結(jié)果,說明構(gòu)造函數(shù)沒有將對象初始化完成。
由此我們可以得出幾條結(jié)論:
構(gòu)造函數(shù):
- 只提供自動初始化成員變量的機會
- 不能保證初始化邏輯一定成功
- 執(zhí)行return 語句后構(gòu)造函數(shù)立即結(jié)束
從而我們知道,構(gòu)造函數(shù)能決定的只是對象的初始狀態(tài),而不是對象的誕生!!!,上面的代碼我們加了return語句后,t1這個對象就沒有真正的被完全構(gòu)造,所以不能正常使用這個對象。
這樣的對象,我們叫它:半成品對象.
半成品對象的概念:
-
初始化操作不能按照預(yù)期完成二得到的對象
-
半成品對象是合法的C++對象,但是同時它也是Bug的重要來源
一般企業(yè)中最難以調(diào)試的Bug,一是野指針(后面文章會寫),其次就是這個半成品對象帶來的Bug。
二階構(gòu)造
那么我們該如何避免這樣的Bug呢?下面就引出二階構(gòu)造的含義:
- 工程開發(fā)中的構(gòu)造過程可分為
- 資源無關(guān)的初始化操作
*不可能出現(xiàn)異常情況的操作 - 需要使用系統(tǒng)資源的操作
*可能出現(xiàn)異常情況,如:內(nèi)存申請,訪問文件
- 資源無關(guān)的初始化操作
二階構(gòu)造大體流程:
實例代碼如下:
我們來分析一下以上代碼:
二階構(gòu)造示例:
第一階段構(gòu)造函數(shù)與第二階段構(gòu)造函數(shù)放到private里面了,外部無法調(diào)用。
但是在public中,定義的是static 型的NewInstance函數(shù),返回TwoPhaseCons類型的對象,那么通過它就可以調(diào)用private里面的構(gòu)造函數(shù)。例如在NewInstance函數(shù)里可以有如下代碼: TwoPhaseCons* ret = new TwoPhaseCons();,因為處于NewInstance內(nèi)部,所以它可以調(diào)用構(gòu)造函數(shù)。
通過判斷語句:if( !(ret && ret->construct()) ) 可以判斷兩個階段的構(gòu)造過程是否都沒有錯誤。
而在main函數(shù)中有一句話:TwoPhaseCons* obj = TwoPhaseCons::NewInstance();這是調(diào)用NewInstance()函數(shù)創(chuàng)建obj 對象,因為構(gòu)造函數(shù)TwoPhaseCons為private類型,所以想創(chuàng)建對象,必須用public中的靜態(tài)創(chuàng)建函數(shù):static TwoPhaseCons* NewInstance(); // 對象創(chuàng)建函數(shù)而不能像之前那樣直接用構(gòu)造函數(shù)創(chuàng)建對象了如:TwoPhaseCons obj;
上面的程序的運行結(jié)果為:
obj = 0x8a0d008
這說明,我們在上面合法的創(chuàng)建看了對象obj。
同時我們也可以看出,用了二階構(gòu)造模式后,對象只能在堆空間上進行構(gòu)造而不能在棧空間上構(gòu)造,這樣好么?答案是肯定的,因為工程上的對象往往是巨大的,一般都會放到堆空間上進行構(gòu)造。
總結(jié):
- 構(gòu)造函數(shù)只能決定對象的初始化狀態(tài)
- 構(gòu)造函數(shù)中初始化操作的失敗不影響對象的誕生
- 初始化不完全的半成品對象是Bug的主要來源
- 二階構(gòu)造人為的將初始化過程分成兩部分
- 二階構(gòu)造能夠確保創(chuàng)建的對象都是完整初始化的
想獲得各種學(xué)習(xí)資源以及交流學(xué)習(xí)的加我:
qq:1126137994
微信:liu1126137994
可以共同交流關(guān)于嵌入式,操作系統(tǒng),C++語言,C語言,數(shù)據(jù)結(jié)構(gòu)等技術(shù)問題!
總結(jié)
以上是生活随笔為你收集整理的【C++深度剖析教程4】C++的二阶构造模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 互联网日报 | 蚂蚁集团成立整改工作组;
- 下一篇: 【剑指offer - C++/Java】