• <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>
            萬星星@豌豆莢 歡迎加入我們
            一個吃軟飯的男人!!!!!我只想寫程序####
            微博:http://weibo.com/wanlianwen
            posts - 172,  comments - 1253,  trackbacks - 0
            獨自一人苦學模板,實在郁悶,翻譯e文逼迫自己學習:(全部寫完后整理)

            8.4 友元
            聲明友元的思想其實很簡單:標識一個類或者函數,對于將其聲明為友元所在的類具有某種特權。但是在以下兩個方面,問題似乎有點復雜:
            1、一個友元聲明只能是一個實體的唯一聲明(注:我還沒理解,不能解釋)
            2、友元函數聲明的同時可以定義。

            友元類在聲明的時候不允許定義,所以一般不會有問題。在模板情況下,唯一一點不同就是可以將類模板的一個特定實例聲明為友元:
            template<typename?T>
            class?Node;

            template
            <typename?T>
            class?Tree{
            ????friend?
            class?Node<T>;
            ????…
            }
            ;
            注意:類模板在被一個類或者類模板聲明為友元的時候必須是可見的,而對于普通的類則沒有這種需求:
            template<typename?T>
            class?Tree{?
            ????friend?
            class?Factory;????????//?OK,?even?if?first?declaration?of?Factory
            ????friend?class?class?Node<T>;??//?ERROR?if?Node?isn't?visible
            }
            ;?

            8.4.1 友元函數
            函數模板的實例可以通過在函數名后面跟一對<>將其聲明為友元。<>里面可以包含模板參數,如果編譯器可以推導出模板參數,可以省略調模板參數:
            template<typename?T1,?typename?T2>
            void?combine(T1,?T2);

            class?Mixer{
            ????friend?
            void?combine<>(int&,?int&);
            ????
            //?OK:?T1?=?int&,?T2?=?int&
            ????friend?void?combine<int,?int>(int,?int);
            ????
            //?OK:?T1?=?int,?T2?=?int
            ????friend?void?combine<char>(char,?int);
            ????
            //?OK:?T1?=?char?T2?=?int
            ????friend?void?combine<char>(char&,?int);
            ????
            //?ERROR:?doesn't?match?combine()?template
            ????friend?void?combine<>(long,?long)?{?}
            ????
            //?ERROR:?definition?not?allowed!
            }
            ;
            (注:在GCC下測試,VS2003不行)
            注意:我們可以對模板進行專門化定義,但是不能對模板實例進行定義,所以聲明模板實例為友元時不能定義。

            如果名字后面跟有<>,有2種可能:
            1、如果名字沒有限定詞(也就是前面沒有::),就不可能是模板實例。如果在聲明友元的地方沒有非模板函數匹配的話,就是函數的首次聲明,聲明同時可以定義。
            2、如果名字有限定詞,那么一定與前面聲明的函數或者模板函數有關,在匹配的時候優先選擇非函數模板而不是函數模板,然而在聲明的時候是不允許定義的。

            下面的例子總結了各種可能性:
            void?multiply?(void*);???//?ordinary?function?

            template?
            <typename?T>?
            void?multiply(T);????????//?function?template?

            class?Comrades?{?
            ????friend?
            void?multiply(int)?{}?
            ?????????????????????????
            //?defines?a?new?function?::multiply(int)?

            ????friend?
            void?::multiply(void*);?
            ?????????????????????????
            //?refers?to?the?ordinary?function?above;?
            ?????????????????????????
            //?not?to?the?multiply<void*>?instance?

            ????friend?
            void?::multiply(int);?
            ?????????????????????????
            //?refers?to?an?instance?of?the?template?

            ????friend?
            void?::multiply<double*>(double*);?
            ?????????????????????????
            //?qualified?names?can?also?have?angle?brackets?
            ?????????????????????????
            //?but?a?template?must?be?visible.?

            ????friend?
            void?::error()?{}?
            ?????????????????????????
            //?ERROR:?a?qualified?friend?cannot?be?a?definition?
            }
            ;?

            (注:在VS2003和規則復合,GCC上編譯完全通過)

            前面例子我們討論了一般類(相對于類模板)里面的友元函數,遵守的規則同樣適用于類模板,但模板參數在確定友元函數的時候會起作用:
            template<typename?T>
            class?Node?{
            ????Node
            <T>*?allocate();
            }
            ;?

            template
            <typename?T>
            class?List?{
            ????friend?Node
            <T>*?Node<T>::allocate();
            }
            ;

            然而,當友元函數在類模板里面聲明并定義的時候會出現有趣的現象,因為模板里面任何東西在未實例化之前都只是聲明而沒有具現。考慮下面的例子:
            template<typename?T>
            class?Creator?{?
            ????friend?
            void?appear()?{??//?a?new?function?::appear(),?but?it?doesn't
            ????????…???????????????????//?exist?until?Creator?is?instantiated
            ????}

            }
            ;

            Creator
            <void>?miracle;??//?::appear()?is?created?at?this?point
            Creator<double>?oops;???//?ERROR:?::appear()?is?created?a?second?time!
            這個例子中模板的兩次實例化導致同一函數定義多次,違反了一次定義規則。

            所以對于上面的情況,我們必須確保類模板的模板參數出現在聲明并定義的友元函數形參里面(除非想阻止多次實例化一個類模板,這好像不太可能)。把這個規律運用到前面那個例子:
            template<typename?T>
            class?Creator?{?
            ????friend?
            void?feed(Creator<T>*){??//?every?T?generates?a?different
            ????????????????????????????????????
            //?function?::feed()
            ????}

            }
            ;

            Creator
            <void>?one;?????//?generates?::feed(Creator<void>*)
            Creator<double>?two;???//?generates?::feed(Creator<double>*)
            這個例子中,Creator每個實例都生成不同的函數。注意這些函數是類模板實例產生的,但函數本身并不是函數模板的實例,而是普通函數。
            還要注意這些函數體定義于類中,默認是內聯的,所以在兩個翻譯單元產生相同的函數是沒有問題的。(注:由于內聯函數基于代碼替代技術,所以一個函數定義所在的h文件被多次包含不會有問題,內聯函數在編譯器看來就是一段代碼。)

            8.4.2 友元模板
            一般情況我們都是把函數模板或者類模板的某一實例聲明為友元,但把模板本身聲明為友元有時候也是非常有用的。這就需要所謂的模板友元,例如:
            class?Manager?{?
            ????template
            <typename?T>
            ????friend?
            class?Task;
            ????
            ????template
            <typename?T>
            ????friend?
            void?Schedule<T>::dispatch(Task<T>*);
            ????
            ????template
            <typename?T>
            ????friend?
            int?ticket()?{
            ????????
            return?++Manager::counter;
            ????}
            ?
            ????
            static?int?counter;
            }
            ;
            和普通友元函數一樣,沒有限定詞且名字后面沒有<>的函數模板在聲明為友元同時可以定義。
            聲明原始函數模板或者原始類模板為友元的時候,所有相關的偏特化以及顯示特例化都自動成為友元。
            (注:測試代碼
            class?Manager?{?
            ????template
            <typename?T>????//?firend?template
            ????friend?class?Task;
            private:
            ????
            int????_dat;
            }
            ;

            template
            <typename?T>
            class?Task?{
            }
            ;

            template
            <>
            class?Task<int>?{????????????//?specialization
            public:
            ????
            void?accessData()
            ????
            {
            ????????_manager._dat?
            =?0;????//?can?access?Manager's?private?data
            ????}

            private:
            ????Manager????_manager;
            }
            ;


            (本節完,汗...... 自己收獲不小)
            posted on 2006-04-06 23:48 萬連文 閱讀(1110) 評論(0)  編輯 收藏 引用 所屬分類: 模板
            簡歷下載
            聯系我

            <2009年6月>
            31123456
            78910111213
            14151617181920
            21222324252627
            2829301234
            567891011

            常用鏈接

            留言簿(66)

            隨筆分類

            隨筆檔案

            相冊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            无码精品久久一区二区三区| 久久狠狠一本精品综合网| 亚洲精品国精品久久99热一| 亚洲欧美日韩久久精品第一区| 亚洲欧美伊人久久综合一区二区 | 久久久久亚洲AV成人网人人软件| 一级女性全黄久久生活片免费 | 思思久久99热只有频精品66| 午夜人妻久久久久久久久| 国产精品成人无码久久久久久 | 一本一本久久A久久综合精品| 久久国产精品成人片免费| 国产精品gz久久久| 天堂久久天堂AV色综合| 精品视频久久久久| 91精品国产综合久久婷婷| 亚洲精品无码久久久| 久久久久久久99精品免费观看| 久久人妻AV中文字幕| 久久久久综合中文字幕| 日本免费一区二区久久人人澡 | 国内精品九九久久久精品| 亚洲精品乱码久久久久久蜜桃| 国产精品久久久久久久久免费 | 国产精品久久久天天影视| 伊人久久大香线蕉av不卡| 亚洲欧美成人久久综合中文网| A级毛片无码久久精品免费| 国产精品久久永久免费| 2021久久国自产拍精品| 精品久久久无码人妻中文字幕| 四虎影视久久久免费| 一本大道久久东京热无码AV| 一本大道加勒比久久综合| 久久99国产精品二区不卡| 国产精品久久久久9999高清| 久久久无码人妻精品无码| 久久久噜噜噜www成人网| 人妻无码久久一区二区三区免费| 狠狠色丁香久久婷婷综合| 久久久久久久久波多野高潮|