日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++深度剖析教程4】C++的二阶构造模式

發布時間:2023/12/10 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++深度剖析教程4】C++的二阶构造模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天學習的是C++中的二階構造模式,二階構造模式只是設計模式中的簡單的模式,是一種軟件設計的方法,并沒有我們想象的那么高深,設計模式也是一樣,只不過是一系列的設計方法,只要我們懂得了原理,那么一切都是相通的。

回顧:構造函數的回顧

關于構造函數:

  • 類的構造函數用于對象的初始化
  • 構造函數與類同名并且沒有返回值
  • 構造函數在對象定義時自動被調用

問題:

1.如何判斷構造函數的執行結果?
2.在構造函數中執行return語句會發生什么?
3.構造函數執行結束是否意味著對象構造成功?

下面我們以碼實例來分析問題:

#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; }

這就是一個普普通通的代碼,用來初始化兩個變量的。編譯輸出結果為:

t1.mi = 1 t1.mj = 2

現在我在構造函數中加一個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; }

執行結果為:

t1.mi = 1 t1.mj = 2527220

很顯然mj變成了一個隨機數,那么說明構造函數在構造對象t1時,執行到return語句后就返回了,并沒有繼續執行,那么到底是不是這樣的呢?我們來做一個試驗就知道了,添加一個bool型變量來判斷構造函數執行到哪里去了,代碼如下:

#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 語句后構造函數立即結束

從而我們知道,構造函數能決定的只是對象的初始狀態,而不是對象的誕生!!!,上面的代碼我們加了return語句后,t1這個對象就沒有真正的被完全構造,所以不能正常使用這個對象。

這樣的對象,我們叫它:半成品對象.

半成品對象的概念:

  • 初始化操作不能按照預期完成二得到的對象

  • 半成品對象是合法的C++對象,但是同時它也是Bug的重要來源

    一般企業中最難以調試的Bug,一是野指針(后面文章會寫),其次就是這個半成品對象帶來的Bug。

二階構造

那么我們該如何避免這樣的Bug呢?下面就引出二階構造的含義:

  • 工程開發中的構造過程可分為
    • 資源無關的初始化操作
      *不可能出現異常情況的操作
    • 需要使用系統資源的操作
      *可能出現異常情況,如:內存申請,訪問文件

二階構造大體流程:

實例代碼如下:

#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; }

我們來分析一下以上代碼:
二階構造示例:

class TwoPhaseCons { private:TwoPhaseCons() // 第一階段構造函數{ }bool construct() // 第二階段構造函數{ return true; } public:static TwoPhaseCons* NewInstance(); // 對象創建函數 };

第一階段構造函數與第二階段構造函數放到private里面了,外部無法調用。
但是在public中,定義的是static 型的NewInstance函數,返回TwoPhaseCons類型的對象,那么通過它就可以調用private里面的構造函數。例如在NewInstance函數里可以有如下代碼: TwoPhaseCons* ret = new TwoPhaseCons();,因為處于NewInstance內部,所以它可以調用構造函數。

TwoPhaseCons* TwoPhaseCons::NewInstance() {TwoPhaseCons* ret = new TwoPhaseCons();// 若第二階段構造失敗,返回 NULL if( !(ret && ret->construct()) ) {delete ret;ret = NULL;}return ret; } TwoPhaseCons* ret = new TwoPhaseCons()//調用第一階段的構造函數,做一些初始化操作,不會引起異常的操作

通過判斷語句:if( !(ret && ret->construct()) ) 可以判斷兩個階段的構造過程是否都沒有錯誤。

而在main函數中有一句話:TwoPhaseCons* obj = TwoPhaseCons::NewInstance();這是調用NewInstance()函數創建obj 對象,因為構造函數TwoPhaseCons為private類型,所以想創建對象,必須用public中的靜態創建函數:static TwoPhaseCons* NewInstance(); // 對象創建函數而不能像之前那樣直接用構造函數創建對象了如:TwoPhaseCons obj;

上面的程序的運行結果為:
obj = 0x8a0d008

這說明,我們在上面合法的創建看了對象obj。

同時我們也可以看出,用了二階構造模式后,對象只能在堆空間上進行構造而不能在棧空間上構造,這樣好么?答案是肯定的,因為工程上的對象往往是巨大的,一般都會放到堆空間上進行構造。

總結:

  • 構造函數只能決定對象的初始化狀態
  • 構造函數中初始化操作的失敗不影響對象的誕生
  • 初始化不完全的半成品對象是Bug的主要來源
  • 二階構造人為的將初始化過程分成兩部分
  • 二階構造能夠確保創建的對象都是完整初始化的

想獲得各種學習資源以及交流學習的加我:
qq:1126137994
微信:liu1126137994
可以共同交流關于嵌入式,操作系統,C++語言,C語言,數據結構等技術問題!

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【C++深度剖析教程4】C++的二阶构造模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。