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

            Shuffy

            不斷的學(xué)習(xí),不斷的思考,才能不斷的進(jìn)步.Let's do better together!
            posts - 102, comments - 43, trackbacks - 0, articles - 19
            [轉(zhuǎn)]http://www.shnenglu.com/tiandejian/archive/2007/04/18/ECPP_06.html

            第6條:         要顯式禁止編譯器為你生成不必要的函數(shù)

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

            class HomeForSale { ... };

            就像每一個(gè)房地產(chǎn)代理商能夠很快指出的,每一間住宅都是獨(dú)一無二的——沒有兩間是完全一樣的。既然如此,為一個(gè) HomeForSale 對(duì)象復(fù)制出一個(gè)副本的想法就顯得沒什么意義了。你怎么能夠復(fù)制那些生來就獨(dú)一無二的東西呢?如果你嘗試去復(fù)制一個(gè) HomeForSale 對(duì)象,那么編譯器則不應(yīng)該接受:

            HomeForSale h1;

            HomeForSale h2;

             

            HomeForSale h3(h1);            // 嘗試復(fù)制 h1 :不應(yīng)通過編譯!

            h1 = h2;                       // 嘗試復(fù)制 h2 :不應(yīng)通過編譯!

            可惜的是,防止這種復(fù)雜問題發(fā)生的方法并不是那么的直截了當(dāng)。通常情況下,如果你希望一個(gè)類不支持某種特定種類的功能,你需要做的僅僅是不去聲明那個(gè)函數(shù)。這一策略對(duì)復(fù)制構(gòu)造器和賦值運(yùn)算符就失靈了,這是因?yàn)椋词鼓悴蛔雎暶鞴ぷ鳎腥藝L試調(diào)用這些函數(shù),編譯器就會(huì)為你自動(dòng)聲明它們。

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

            解決問題的關(guān)鍵是,所有編譯器生成的函數(shù)都是公共的。為了防止編譯器生成這些函數(shù),你必須自己聲明,但是現(xiàn)在沒有什么要求將這些函數(shù)聲明為公共的。取而代之,你應(yīng)該將復(fù)制構(gòu)造器和賦值運(yùn)算符聲明為私有的。通過顯式聲明一個(gè)函數(shù),你就可以防止編譯器去自動(dòng)生成這個(gè)函數(shù),并且,通過將函數(shù)聲明為 private 的,你便可以防止人們?nèi)フ{(diào)用它。

            在大多數(shù)情況下,這一方案并不是十分簡(jiǎn)單明了,這是因?yàn)閿?shù)據(jù)成員和友元函數(shù)仍然可以調(diào)用你的私有函數(shù)。除非,你足夠的聰明,沒有去定義這些函數(shù)。如果一些人由于疏忽大意而調(diào)用了其中的任一個(gè),他們會(huì)在連接時(shí)遇到一個(gè)錯(cuò)誤。把成員函數(shù)聲明為 private 的但是不去實(shí)現(xiàn)它們,這一竅門已經(jīng)成為編程常規(guī),它應(yīng)用于多個(gè) C++ I/O 流的庫(kù)中,用以防止復(fù)制。比如,你可以參考標(biāo)準(zhǔn)庫(kù)中 ios_base basic_ios sentry 的實(shí)現(xiàn)。你會(huì)發(fā)現(xiàn)在各種情況下,復(fù)制構(gòu)造器和賦值運(yùn)算符都聲明為 private 而且沒有得到定義。

            對(duì) HomeForSale 使用這一技巧十分簡(jiǎn)單:

            class HomeForSale {

            public:

             ...

            private:

             ...

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

             HomeForSale& operator=(const HomeForSale&);

            };

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

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

            如果你將復(fù)制構(gòu)造器和賦值運(yùn)算符聲明為 private 的,并且位于 HomeForSale 的外部,放置在一個(gè)專門設(shè)計(jì)用來防止復(fù)制的基類中,那么在編譯時(shí)就排出這些連接時(shí)錯(cuò)誤便成為可能(這是件好事——早期發(fā)現(xiàn)錯(cuò)誤要比晚些更理想)。這一基類極其簡(jiǎn)單:

            class Uncopyable {

            protected:                            // 允許派生類存在構(gòu)造器和析構(gòu)器

             Uncopyable() {}

             ~Uncopyable() {}

             

            private:

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

             Uncopyable& operator=(const Uncopyable&);

            };

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

            class HomeForSale: private Uncopyable {

               ...                  // 這一類不再聲明復(fù)制構(gòu)造器和賦值運(yùn)算符。

            };

            這樣做是可行的,這是因?yàn)槿绻腥耍ㄉ踔潦且粋€(gè)成員或友元函數(shù))嘗試復(fù)制一個(gè) HomeForSale 對(duì)象,編譯器將會(huì)嘗試自動(dòng)生成一個(gè)復(fù)制構(gòu)造器和一個(gè)賦值運(yùn)算符。就像 12 中所解釋的,這些函數(shù)由編譯器自動(dòng)生成的版本會(huì)嘗試調(diào)用它們基類中的這一部分,顯然這些調(diào)用只能吃到閉門羹,這是因?yàn)閺?fù)制操作在基類中是私有的。

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

            需要記住的

            為了禁用編譯器自動(dòng)提供的功能,你必須將相關(guān)的成員函數(shù)聲明為 private 的,同時(shí)不要實(shí)現(xiàn)它。使用一個(gè)像 Uncopyable 這樣的類來完成這一工作。

            性做久久久久久久久浪潮| 狠狠久久亚洲欧美专区| 免费精品99久久国产综合精品| 一本大道加勒比久久综合| 中文字幕亚洲综合久久菠萝蜜| 97视频久久久| 91久久福利国产成人精品| 成人精品一区二区久久| 久久中文骚妇内射| 久久久久这里只有精品| 久久久久人妻精品一区 | 国产精品99精品久久免费| 香蕉99久久国产综合精品宅男自 | avtt天堂网久久精品| 国产精品美女久久久久av爽| 久久国产劲爆AV内射—百度| 久久精品国产亚洲一区二区三区| 国产精品岛国久久久久| 久久国产免费直播| 久久精品国产WWW456C0M| 国产成人久久激情91| 久久精品国产亚洲AV蜜臀色欲| 97超级碰碰碰碰久久久久| 国产亚洲综合久久系列| 亚洲中文字幕久久精品无码喷水| 久久久亚洲AV波多野结衣| 亚洲国产成人久久精品影视| 亚洲精品乱码久久久久久自慰 | 久久国语露脸国产精品电影| 久久久噜噜噜久久| 丁香五月综合久久激情| 亚洲国产精品久久久久婷婷软件| 久久午夜伦鲁片免费无码| 久久久久亚洲av无码专区导航| 久久成人国产精品免费软件| 伊人久久大香线蕉AV一区二区 | 欧美日韩中文字幕久久伊人| 精品免费久久久久久久| 99久久久国产精品免费无卡顿 | 色婷婷噜噜久久国产精品12p| 久久精品成人一区二区三区|