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

            洛譯小筑

            別來無恙,我的老友…
            隨筆 - 45, 文章 - 0, 評論 - 172, 引用 - 0
            數(shù)據(jù)加載中……

            [ECPP讀書筆記 條目6] 要顯式禁止編譯器為你生成不必要的函數(shù)

            真實的房地產代理商的工作是出售房屋,而一個為房產代理商提供支持的軟件系統(tǒng)自然要用一個類來代表要出售的房屋:

            class HomeForSale { ... };

            所有房地產代理商能夠很輕松的指出,每套房產都是獨一無二的——沒有兩套是完全一樣的。既然如此,為一個HomeForSale對象復制出一個副本的想法就顯得沒什么意義了。你怎么能夠復制那些生來就獨一無二的東西呢?如果你嘗試去復制一個HomeForSale對象,那么編譯器則不應該接受:

            HomeForSale h1;

            HomeForSale h2;

             

            HomeForSale h3(h1);                // 嘗試復制h1:不應通過編譯!

            h1 = h2;                           // 嘗試復制h2:不應通過編譯!

            可惜的是,防止這種復雜問題發(fā)生的方法并不是那么直截了當。通常情況下,如果你希望一個類不支持某種特定的功能,你需要做的僅僅是不去聲明那個函數(shù)。然而這一策略對復制構造函數(shù)和拷貝賦值運算符就失效了,這是因為,即使你不做聲明,而一旦有人嘗試調用這些函數(shù),編譯器就會為你自動聲明它們(參見條目5)。

            這會使你便陷入困境。如果你不聲明一個復制構造函數(shù)或者賦值運算符,編譯器可能就會幫你去做,你的類就會支持對象復制。從另一個角度說,如果你確實聲明了這些函數(shù),你的類仍然支持復制。但是現(xiàn)在的目標是防止復制!

            解決問題的關鍵是,所有編譯器生成的函數(shù)都是公共的。為了防止編譯器生成這些函數(shù),你必須自己聲明,但是現(xiàn)在沒有什么要求你將這些函數(shù)聲明為公共的。取而代之,你應該將復制構造函數(shù)和賦值運算符聲明為私有的。通過顯式聲明一個函數(shù),你就可以防止編譯器去自動生成這個函數(shù),同時,通過將函數(shù)聲明為private的,你便可以防止人們去調用它。

            差不多了。但是這一方案也沒有那么傻瓜化,這是因為成員函數(shù)和友元函數(shù)仍然可以調用你的私有函數(shù)。除非你足夠的聰明,沒有去定義這些成員或友元。如果一些人由于疏忽大意而調用了其中的任意一個,他們會在程序連接時遇到一個錯誤。把成員函數(shù)聲明為private的但是不去實現(xiàn)它們,這一竅門已經成為編程常規(guī),在C++的I/O流的庫中的一些類,都會采用這種方法來防止復制。比如,你可以參考標準庫中ios_base、basic_iossentry的實現(xiàn)。你會發(fā)現(xiàn)在各種情況下,復制構造函數(shù)和拷貝賦值運算符都聲明為private而且沒有得到定義。

            HomeForSale使用這一技巧十分簡單:

            class HomeForSale {

            public:

              ...

            private:

              ...

              HomeForSale(const HomeForSale&); // 只有聲明

              HomeForSale& operator=(const HomeForSale&);

            };

            你會發(fā)現(xiàn)我省略了函數(shù)參數(shù)的名稱。這樣做并不是必需的,這僅僅是一個普通慣例。畢竟這些代碼不會得到實現(xiàn),而且很少會用到,那么給這些參數(shù)命名又有什么用呢?

            通過上文中類的聲明,編譯器會防止客戶嘗試復制HomeForSale對象,如果你不小心在成員函數(shù)或者友元函數(shù)中這樣做了,那么你的程序將無法得到連接。

            如果你將復制構造函數(shù)和拷貝賦值運算符聲明為private的,并且將二者移出HomeForSale的內部,放置在一個專門設計用來防止復制的基類中,那么在編譯時就排除這些原本是連接時的錯誤便成為可能(這是件好事——早期發(fā)現(xiàn)錯誤要比晚些更理想)。這一基類極其簡單:

            class Uncopyable {

            protected:                         // 允許派生類存在構造函數(shù)和析構函數(shù)

              Uncopyable() {}

              ~Uncopyable() {}

             

            private:

              Uncopyable(const Uncopyable&);   // 但禁止復制

              Uncopyable& operator=(const Uncopyable&);

            };

            為了防止HomeForSale對象被復制,我們所需要做的僅僅是讓其繼承Uncopyable

            class HomeForSale: private Uncopyable {

              ...                              // 這一類不再聲明復制構造函數(shù)和賦值運算符

            };

            這樣做是可行的,這是因為如果有人(甚至是一個成員或友元函數(shù))嘗試復制一個HomeForSale對象,編譯器將會嘗試自動生成一個復制構造函數(shù)和一個拷貝賦值運算符。就像條目12中所解釋的,這些函數(shù)由編譯器自動生成的版本會嘗試調用它們基類中的這一部分,顯然這些調用只能吃到閉門羹,這是因為復制操作在基類中是私有的。

            Uncopyable的實現(xiàn)和應用存在一些微妙的問題,諸如繼承自Uncopyable的類不一定必須為public的(參見條目32和條目39),Uncopyable的析構函數(shù)不一定必須為虛函數(shù)(參見條目7)。由于Uncopyable不包含任何數(shù)據(jù),它適合作為空基類優(yōu)化方案(參見條目39),但是由于它是一個基類,使用這一技術將導致多重繼承(參見條目40)。然而,多重繼承在某種情況下會使空基類優(yōu)化失去作用(同樣,請參見條目39)??傮w來說,你可以忽略這些微妙的問題,僅僅使用上文中的Uncopyable,因為它會像所承諾的那樣精確地完成工作。你也可以使用Boost版本(條目55)。那個類叫做noncopyable。它是一個優(yōu)秀的類,我只是發(fā)現(xiàn)它的名字顯得有些不自然(un-natural),呃,“非”自然(non-natural)。

            時刻牢記

            為了禁用編譯器自動提供的功能,你必須將相關的成員函數(shù)聲明為private的,同時不要實現(xiàn)它。方法之一是:使用一個類似于Uncopyable的基類。

            posted on 2007-04-18 23:21 ★ROY★ 閱讀(1049) 評論(1)  編輯 收藏 引用 所屬分類: Effective C++

            評論

            # re: 【翻譯】Effective C++ (第6條:要顯式禁止編譯器為你生成不必要的函數(shù))  回復  更多評論   

            // 這一類不再聲明復制構造器和賦值運算符。

            這句話蠻重要,呵呵
            2007-05-22 15:05 | recorder
            亚洲中文久久精品无码| 香蕉久久AⅤ一区二区三区| 精品久久人妻av中文字幕| 久久精品亚洲精品国产色婷| 久久青青草原亚洲av无码app| 久久精品午夜一区二区福利| 热99re久久国超精品首页| 青青热久久国产久精品| 久久天天躁狠狠躁夜夜躁2O2O| 久久国产成人精品麻豆| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 久久这里只有精品首页| 亚洲国产精品无码久久青草 | 综合久久精品色| 狠狠色婷婷久久一区二区三区| 久久久久亚洲AV综合波多野结衣| 久久夜色精品国产网站| 久久婷婷五月综合成人D啪| 国产精品久久午夜夜伦鲁鲁| 性做久久久久久久久老女人| 国产美女久久精品香蕉69| 无码国内精品久久综合88| 国产免费久久久久久无码| 久久婷婷国产综合精品| 免费精品久久天干天干| 久久精品中文字幕第23页| 国产精品久久久久久福利漫画| 久久久噜噜噜久久中文字幕色伊伊 | 一本色道久久88综合日韩精品 | 国产99久久久国产精品~~牛| 日韩人妻无码精品久久免费一| 亚洲Av无码国产情品久久| 久久精品亚洲欧美日韩久久| 成人国内精品久久久久影院VR| 狠狠色丁香婷综合久久| 久久精品草草草| 办公室久久精品| 久久婷婷色综合一区二区| 久久亚洲精品国产精品婷婷| 久久有码中文字幕| 性做久久久久久久久老女人|