• <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 萬連文 閱讀(1117) 評論(0)  編輯 收藏 引用 所屬分類: 模板
            簡歷下載
            聯系我

            <2006年4月>
            2627282930311
            2345678
            9101112131415
            16171819202122
            23242526272829
            30123456

            常用鏈接

            留言簿(66)

            隨筆分類

            隨筆檔案

            相冊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久99精品久久久久久| 中文字幕日本人妻久久久免费| 少妇无套内谢久久久久| 麻豆久久| 人妻少妇久久中文字幕一区二区| 精品国产乱码久久久久久郑州公司| 日本精品久久久久中文字幕| 狠狠色丁香婷婷久久综合| 亚洲AV无码久久| 亚洲v国产v天堂a无码久久| 国产成人久久精品一区二区三区| 91久久精品国产91性色也| 亚洲日韩中文无码久久| 久久久九九有精品国产| 欧美亚洲国产精品久久高清| 青青草国产精品久久久久| 精品国产乱码久久久久久人妻| 久久受www免费人成_看片中文| 欧美亚洲国产精品久久蜜芽| 亚洲国产成人乱码精品女人久久久不卡 | 思思久久99热只有频精品66| 国内精品久久国产大陆| 欧美国产成人久久精品| 久久精品无码专区免费| 国产成人99久久亚洲综合精品| 国产精品久久久久久久| 国产精品一久久香蕉国产线看| 色播久久人人爽人人爽人人片aV | 国产精品九九久久免费视频 | 99久久www免费人成精品| 色欲av伊人久久大香线蕉影院| 亚洲日本va午夜中文字幕久久| 超级碰久久免费公开视频| 成人久久精品一区二区三区| 日韩人妻无码精品久久久不卡| 伊人久久精品无码二区麻豆| 伊人久久国产免费观看视频| 中文字幕无码av激情不卡久久| 亚洲人成网站999久久久综合| 久久久久久青草大香综合精品| 久久99亚洲综合精品首页|