• <label id="pxtpz"><meter id="pxtpz"></meter></label>
      1. <span id="pxtpz"><optgroup id="pxtpz"></optgroup></span>

        當前位置:雨林木風下載站 > 技術開發教程 > 詳細頁面

        由始至終----構造與析構(轉轉)

        由始至終----構造與析構(轉轉)

        更新時間:2022-05-03 文章作者:未知 信息來源:網絡 閱讀次數:

        由始至終

         ----構造與析構

        作者:HolyFire

        我們在平時的生活中一般會總結出一些規律,早上起床會刷牙洗臉,晚上會洗澡睡覺,這些都成了慣例。使用瓶裝調味品時先將瓶蓋打開,用完后將瓶蓋蓋上。這是一種好習慣。但是有些人不同,他們往往偷懶,一個常常不刷牙不洗臉不洗澡的人會有體味,東西放得亂七八糟的人生房間很不整潔。這些都是我們不希望看到的。當然編程中我們也不希望代碼亂七八糟。

        使用一個未初始化的變量簡直就是災難,使用一個未初始化的指針將導致崩潰。這是我的忠告。在C++中初始化不會有附加的效果,不會降低效率,我們要做的是養成好習慣,產生一個對象的時候就將它初始化。

        對于

        Object.Init();

        Object.Free();

        這樣的調用并不是很困難,要記住他也不是難事,但是誰都不能保證他永遠不會忘記,更糟糕的是

        Object.Init();

        Object.Free();

        沒有配對使用

        Object.Init();

        Object.Free();

        Object.Free();



        Object.Init();

        Object.Init();

        Object.Free();

        會帶來什么樣的結果,誰也不知道,而且這樣的錯誤,編譯器不會報錯。這是多么可怕的錯誤,一個程序員最怕遇上的就是這樣的邏輯錯誤,它可能為了找這樣的一個錯誤花上一整天時間。

        讓我們看看有什么好的辦法。

        一個對象按時間來分析,一般有三個階段,出生,活動,死亡。與我們要做的有什么相關之處呢,初始化,運行,釋放。很好,對照一下,我們發現在對象出生的時候初始化,死亡的時候釋放,如果這一切能用這樣的機制來操作,我們就再也不用擔心會由于忘記或錯誤的使用帶來麻煩了。

        C++里就提供了這樣的機制。使用他有個約定

        class Object{

        public:

         Object(); //與類同名的函數,該函數沒有返回值,叫做構造函數

        ~Object();//類似的,在構造函數名前加一個取反符號,叫做析構函數

        };

        構造函數將在對象產生的時候調用

        析構函數將在對象銷毀的時候調用

        調用的過程和實現方法由編譯器完成,我們只要記住他們調用的時間就行了,而且他們的調用是自動完成的,不需要我們控制。

        #include <iostream>

        using namespace std;

        class Object{

        public:

         Object(){ cout << "Object ON!" << endl; }

         ~Object(){ cout << "Object OFF!" << endl; }

        };

        void main()

        {

         Object o;

        }

        運行結果

        Object ON!

        Object OFF!

        構在函數和析構函數確實的執行了

        現在我們來一個應用的例子

        一個字符串類,它需要保存字符串的內容,但是它不知道字符串的大小,那么設計這個字符串類的時候,保存字符串的成員變量就不能用固定大小的數組,而是用可以間接操作數組的指針。

        #include <iostream>

        #include <string.h>

        using namespace std;

        class string{

        private:

         char * data;

        public:

         string(){ data = NULL; }

         string( char * str )

        {

        cout << "Copy string: " << str << endl;

        data = new char[ strlen(str) + 1 ];

        memcpy( data , str , strlen(str) + 1 );

        }

         char * Data(){ return data; }

         ~string()

        {

        if( data )

         {

         cout << "Free string: " << data << endl;

         delete data;

         }

        }

        };

        void main()

        {

         {

        string s("abcd");

         cout <<"Show String: " << s.Data() <<endl;

        }

        cin.get();

        }

        Copy string: abcd //執行了string::string( char * str ) 構造函數

        Show String: abcd

        Free string: abcd //由于在{}中產成的對象是臨時對象,它的生命期在}后就結束了,所以string::~string() 析構函數被調用

        申請內存和釋放內存的操作自動完成了,構造函數和析構函數的目的在于一個類可以象普通類型一樣初始化和釋放,從而保證了封裝。

        上面的例子有兩個構造函數,這么什么大不了的,我們看過《面面俱到----重載》得都知道,重載的把戲。

        要注意的是構造函數可以有參數,在繼承中如何處理呢。

        class mystring : public string{

        public:

         mystring( char * str ):string( str ){ }

        }

        mystring( char * str ):string( str )

        記住這樣的形式,給自己的父類傳遞函數就用這樣的書寫格式,這是一個約定。

        構造函數后面加上一個:表示后面是一個初始化序列,說它是一個序列是因為它可以初始化多個成員變量,在初始化序列里調用向父類傳遞參數是為了保證類的產生的順序,先產生父類,然后是子類。使用初始化有個好處就是可以提高效率。

        string(){ data = NULL; }

        可以改寫成

        string():data(NULL){ }

        他的作用是產生成員變量char * data時將他的值置為NULL。從而少了data = NULL;這步操作。

        注意,這里構造和析構有一個順序問題,就是構造時應該從基類開始按繼承的層次順序調用,析構的時候順序正好相反。這樣處理是因為,子類可能在構造函數里使用父類的成員變量,如果父類還沒有創建,那就會有問題,而析構的時候,如果父類先析構,也會有這樣的問題。

        析構函數還有一個能否正確運行的問題。

        #include <iostream>

        using namespace std;

        class One{

        public:

         One(){ cout << "One ON!" << endl; }

         ~One(){ cout << "One OFF!" << endl; }

        };

        class Two : public One{

        public:

         Two(){ cout << "Two ON!" << endl; }

         ~Two(){ cout << "Two OFF!" << endl; }

        };

        class Three : public Two{

        public:

         Three(){ cout << "Three ON!" << endl; }

         ~Three(){ cout << "Three OFF!" << endl; }

        };

        void main()

        {

         Three three;

        }

        運行結果

        One ON!

        Two ON!

        Three ON!

        Three OFF!

        Two OFF!

        One OFF!

        正確

        void main()

        {

         Three * three = new Three;

        delete three;

        }

        運行結果

        One ON!

        Two ON!

        Three ON!

        Three OFF!

        Two OFF!

        One OFF!

        正確

        void main()

        {

         One * three = new Three;

        delete three;

        }

        運行結果

        One ON!

        Two ON!

        Three ON!

        One OFF!

        不好了,Two和Three的析構都沒有運行,怎么會這樣,原來One * three指出了指針指向的是一個One類的對象。如何得到正確的結果呢,如果能讓One類記住被繼承后的變化就好了。

        對了!虛函數,在《后入為主----虛函數》中可以知道,虛函數有這個特性,不信試試看。

        class One{

        public:

         One(){ cout << "One ON!" << endl; }

         virtual ~One(){ cout << "One OFF!" << endl; }

        };

        void main()

        {

         One * three = new Three;

        delete three;

        }

        運行結果

        One ON!

        Two ON!

        Three ON!

        Three OFF!

        Two OFF!

        One OFF!

        正確

        這個特點很重要,我們要牢牢記住,我們稱這種方法為“虛析構”,在多態里運用非常廣泛,也是編寫可復用代碼的一個重要技巧。

        構造和析構的作用機制就是自動化,簡化編程的復雜度。還有要記住的是,在一個類的構造函數里分配了的資源盡量要記得在該類的析構函數里釋放,當然也允許提前釋放,你可以在析構函數里判斷它是否已經釋放,如果沒有就釋放。這就是----由始至終,它間接的描述了一個對象的生和死(記住這一點很重要,因為我以后會講到如何運用這個特性控制對象的生死)。

        溫馨提示:喜歡本站的話,請收藏一下本站!

        本類教程下載

        系統下載排行

        主站蜘蛛池模板: 亚洲中文字幕无码mv| 亚洲av无码一区二区乱子伦as| 97无码免费人妻超级碰碰夜夜| 国产hs免费高清在线观看| 亚洲国产另类久久久精品黑人| 亚洲乱码在线观看| a级毛片毛片免费观看永久| 91嫩草国产在线观看免费| 亚洲午夜福利在线观看| 亚洲色欲色欲www在线播放| 日韩精品无码区免费专区 | 亚洲av中文无码乱人伦在线播放 | 免费观看无遮挡www的小视频| 国产免费资源高清小视频在线观看| 亚洲人成网站在线播放2019| 久久久久成人精品免费播放动漫| 免费人成在线观看视频播放| 亚洲欧洲日韩国产一区二区三区| 色吊丝最新永久免费观看网站| 亚洲人成影院在线| 久久久久久噜噜精品免费直播 | 亚洲国产成人私人影院| 亚洲视频免费在线播放| 亚洲gv白嫩小受在线观看 | 国产又大又长又粗又硬的免费视频 | 色爽黄1000部免费软件下载| 久久久久久国产a免费观看黄色大片| 亚洲精品无码国产| 222www在线观看免费| 蜜臀亚洲AV无码精品国产午夜.| 啦啦啦高清视频在线观看免费| 国产亚洲综合精品一区二区三区| 免费视频淫片aa毛片| 国产精品99爱免费视频| 国产精品亚洲产品一区二区三区| 三年片在线观看免费观看大全中国 | 猫咪免费人成网站在线观看| 亚洲欧美乱色情图片| 国产AV无码专区亚洲AWWW| 曰批免费视频播放免费| 亚洲av麻豆aⅴ无码电影|