• <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++

            婷婷五月深深久久精品| 精品国产综合区久久久久久| 久久中文字幕人妻丝袜| 久久综合偷偷噜噜噜色| 久久精品中文闷骚内射| 精品99久久aaa一级毛片| 久久国语露脸国产精品电影| 国产精品久久久久久久久免费 | 国产精品亚洲综合久久| 国产精品久久久久久久久鸭| 亚洲国产香蕉人人爽成AV片久久| 亚洲国产美女精品久久久久∴| 国产视频久久| 国产精品福利一区二区久久| 一级A毛片免费观看久久精品| 国产一区二区三区久久精品| 久久精品国产亚洲αv忘忧草| 国产亚州精品女人久久久久久 | 欧洲性大片xxxxx久久久| 色综合久久久久久久久五月| 久久久久久毛片免费看| 国产精品久久毛片完整版| 久久精品免费一区二区| 一本色道久久88综合日韩精品 | 久久久久人妻一区精品性色av| 色综合久久久久综合99| 91久久精品电影| 久久久中文字幕| 久久久国产精品福利免费| 国产精品久久久久久影院| av午夜福利一片免费看久久| 嫩草伊人久久精品少妇AV| 久久久久精品国产亚洲AV无码| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 久久精品中文字幕一区| 一级a性色生活片久久无| 中文字幕精品无码久久久久久3D日动漫| 91麻精品国产91久久久久| 精品精品国产自在久久高清| 亚洲国产精品久久| 久久se精品一区二区影院|