• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Benjamin

            靜以修身,儉以養德,非澹薄無以明志,非寧靜無以致遠。
            隨筆 - 397, 文章 - 0, 評論 - 196, 引用 - 0
            數據加載中……

            C++基本概念之構造函數(constructor)(一)

            1.功能:創建(build objects)對象,將一連串的隨意的內存位變對象,也分配資源(memory, files, semaphores, sockets等),"ctor" 是構造函數(constructor)典型的縮寫。
            2.假定List是個類名,List x和 List x()的區別:前者聲明了一個List對象,后者則是一個函數,返回List類型。
            3.能否在一個構造函數中調用另一個構造函數?答案是否定的。
            假設類Fro有兩個構造函數Foo::Foo(char x)和Foo::Foo(char x,int y),那么下面的代碼
            class Foo {
             public:
               Foo(char x);
               Foo(char x, int y);
               ...
             };
             
             Foo::Foo(char x)
             {
               
            ...
               Foo(x, 0);  
            // this line does NOT help initialize the this object!!to initialize a temporary(臨時量)local object (not this), it immediately destructs  that temporary when control flows over,   
               
            ...
             }
            也可以組合這兩個構造函數,通過默認參數
            class Foo {
             public:
               Foo(char x, int y=0);  // this line combines the two constructors
               
            ...
             };
            如果沒有默認參數可用,那么我可以共享公用代碼在私有的Init函數中,如:
            class Foo {
             public:
               Foo(char x);
               Foo(char x, int y);
               ...
             private:
               void init(char x, int y);
             };
             
             Foo::Foo(char x)
             {
               init(x, int(x) + 7);
               
            ...
             }
             
             Foo::Foo(char x, int y)
             {
               init(x, y);
               
            ...
             }
             
             void Foo::init(char x, int y)
             {
               
            ...
             }

            不要嘗試把它用在布局new(placemement new)中,有些人認為可以new(this) Foo(x, int(x)+7)在Foo::Foo(char)中,這是絕對錯誤的。它會影響對象的構建位(constructed bits)。
            4.默認構造函數(default constructor )的參數可以使沒有,也可以使默認的參數。如:
            class Fred {
             public:
               Fred();   // Default constructor: can be called with no args
               
            ...
             }; 或
            class Fred {
             public:
               Fred(int i=3, int j=5);   // Default constructor: can be called with no args
               
            ...
             };
            5.建立對象數組時,哪個構造函數將被調用:
            如果沒有默認構造函數,那么創建對象數組將會出錯。如:
            class Fred {
             public:
               Fred(int i, int j);       assume there is no default constructor
               
            ...
             };
             
             int main()
             {
               Fred a[10];              
             ERROR: Fred doesn't have a default constructor
               Fred* p = new Fred[10];  
             ERROR: Fred doesn't have a default constructor
               
            ...
             }
            如果用std::vector<Fred> ,則可以不用默認構造函數。如:
            #include <vector>
             
             int main()
             {
               std::vector<Fred> a(10, Fred(5,7));   the 10 Fred objects in std::vector a will be initialized with Fred(5,7)
               
            ...
             }
            也可以現實初始化數組:也可以用placement new來手工初始化數組元素
            class Fred {
             public:
               Fred(int i, int j);       assume there is no default constructor
               
            ...
             };
             
             int main()
             {
               Fred a[10] = {
                 Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7),  
            // The 10 Fred objects are
                 Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7), Fred(5,7)   
            // initialized using Fred(5,7)
               };
               
            ...
             }

            一般的我們用vector來替代數組。
            6.構造函數中如何使用初始化列表(initialization lists)和賦值(assignment)
            在構造中使用初始化列表比賦值更有效率,后者比前者多了一個臨時變量,多了這個臨時變量的創建和銷毀的開銷。但是在內置數據類型(int,float等)時,二者差別不大。
            另一種情況是在構造中的成員對象會被以默認構造函數完整的構造,會分配一些缺省狀態下的內存或是文件,這樣如果在構造中如果使用表達式或復制失敗,是沒辦法來釋放資源或關閉文件的。
            在下面情況下不易使用初始化列表:類有兩個構造函數并且需要初始化這個數據成員按照不同的順序,或是有兩個數據成員自引用,或數據成員需要引用this對象,或者拋出一個異常之前要初始化這個this成員等。
            7.構造函數可以使用this指針嗎?可以,但是小心使用,甚至于在初始化列表中使用它。
            可以使用的情況:構造函數的函數體(或構造函數所調用的函數)能可靠地訪問基類中聲明的數據成員和/或構造函數所屬類里聲明的數據成員。這是因為所有這些數據成員被保證在構造函數函數體開始執行時已經被完整的建立。
            構造函數的函數體(或構造函數所調用的函數)不能向下調用被派生類重定義的虛函數。無論你如何調用虛成員函數:顯式使用this指針(如,this->method()),隱式的使用this指針(如,method()),或甚至在this對象上調用其他函數來調用該虛成員函數,原因:在基類的構造函數執行期間,派生類對象還未產生。
            下面的情況有時是可行的:如果傳遞 this 對象的任何一個數據成員給另一個數據成員的初始化程序,你必須確保該數據成員已經被初始化。他的優點是不依賴編譯器,但是你必須知道一些語言規則(例如,基類子對象首先被初始化(如果有多重和/或虛繼承,則查詢這個次序!),然后類中定義的數據成員根據在類中聲明的次序被初始化),如果不知道就不要使用這個this指針。
            8.命名的構造函數法(Named Constructor Idiom):
            作用就就是區分多個構造函數。
            結構:把構造放到private或protected處,提供一個返回對象的public static 方法。每種不同的構造對象的方法都有一個這樣的靜態方法。例子:
            class Point {
             public:
               Point(float x, float y);     // Rectangular coordinates
               Point(float r, float a);     
            // Polar coordinates (radius and angle)
               
            // ERROR: Overload is Ambiguous: Point::Point(float,float)
             };
             
             int main()
             {
               Point p = Point(5.7, 1.2);   
            // Ambiguous: Which coordinate system?
               
            ...
             }
            解決方法就是使用Named Constructor Idiom
            #include <cmath>               // To get sin() and cos()
             
             class Point {
             public:
               static Point rectangular(float x, float y);      
            // Rectangular coord's
               static Point polar(float radius, float angle);   
            // Polar coordinates
               
            // These static methods are the so-called "named constructors"
               
            ...
             private:
               Point(float x, float y);     
            // Rectangular coordinates
               float x_, y_;
             };
             
             inline Point::Point(float x, float y)
               : x_(x), y_(y) { }
             
             inline Point Point::rectangular(float x, float y)
             { return Point(x, y); }
             
             inline Point Point::polar(float radius, float angle)
             { return Point(radius*cos(angle), radius*sin(angle)); }


            int main()
             {
               Point p1 = Point::rectangular(5.7, 1.2);   // Obviously rectangular
               Point p2 = Point::polar(5.7, 1.2);         
            // Obviously polar
               
            ...
             }

            如果Point有派生類,構造就放在protected中。

            posted on 2009-12-05 01:41 Benjamin 閱讀(3117) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

            AAA级久久久精品无码片| 伊人久久综合成人网| 久久996热精品xxxx| 中文字幕亚洲综合久久菠萝蜜 | 久久人人爽人人爽人人AV东京热| 久久天天躁夜夜躁狠狠躁2022| 久久狠狠高潮亚洲精品| 国产香蕉97碰碰久久人人| 久久国产欧美日韩精品| 国产精品成人99久久久久| 中文字幕无码免费久久| 久久成人永久免费播放| 久久香蕉超碰97国产精品| 日本精品久久久久久久久免费| 精品国产乱码久久久久久郑州公司| 久久精品国产清自在天天线| 久久久无码精品亚洲日韩按摩 | 久久天堂AV综合合色蜜桃网| 久久精品无码av| 久久久九九有精品国产| 久久人人爽爽爽人久久久| 色综合久久久久综合99| 精品乱码久久久久久夜夜嗨 | 国产成人精品久久亚洲高清不卡 | 久久这里有精品视频| 91精品婷婷国产综合久久| 久久久无码人妻精品无码| 无码超乳爆乳中文字幕久久| 久久99这里只有精品国产| 亚洲精品国产第一综合99久久| 久久99亚洲综合精品首页| 久久婷婷国产麻豆91天堂| 久久国产精品无码HDAV| 国产成人精品白浆久久69| 亚洲AV无码久久精品狠狠爱浪潮| 最新久久免费视频| 人人狠狠综合88综合久久| 偷偷做久久久久网站| 91麻豆国产精品91久久久| 久久精品国产99国产精品导航 | 国产精品久久久99|