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

            Note of Justin

            關于工作和讀書的筆記

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              47 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

            留言簿(14)

            搜索

            •  

            積分與排名

            • 積分 - 52490
            • 排名 - 433

            最新評論

            閱讀排行榜

            評論排行榜

            [原創(chuàng)文章歡迎轉載,但請保留作者信息]
            Justin 于 2010-05-01



            大師的課上到46堂了,今天課前要求復習一下24課的內容。
            如果你懶得自己去看,這里大概提一下:24課說的是如果在實際調 用中,某個函數(shù)的任何一個參數(shù)都有可能是其他類型數(shù)據(jù)通過“類型轉換”轉換過來的,這個函數(shù)最好是寫成非成員函數(shù)。(哪 怕回去24節(jié)看,掃一遍書上的例子也知道是什么意思了)

            現(xiàn)在把24課的內容升級為模板,就有了下面的代碼:
            template?typename?T>
            class?Rational?{
            ???
            public:
            ??????Rational(
            const?T&?num?=?0,?const?T&?denom?=?1)
            ??????{
            ?????????_numerator?
            =?num;
            ?????????_denominator?
            =?denom;
            ??????}
            #if?OPTION2
            ??????friend?
            const?Rational?operator*(const?Rational&?lhs,?const?Rational&?rhs);
            #endif
            #if?OPTION3
            friend?
            const?Rational?operator?*?(const?Rational&?lhs,?const?Rational&?rhs)
            {
            ???
            return?Rational(lhs.numerator()?*?rhs.numerator(),?lhs.denominator()?*?rhs.denominator());
            }
            #endif

            ??????
            const?T?numerator()?const?{?return?_numerator;?}
            ??????
            const?T?denominator()?const?{?return?_denominator;?}

            ???
            private:
            ??????T?_numerator;
            ??????T?_denominator;
            ??????
            //..
            };
            #if?OPTION1?||?OPTION2
            template?
            typename?T>
            const?RationalT>?operator?*?(const?RationalT>&?lhs,?const?RationalT>&?rhs)
            {
            ???
            return?RationalT>?(lhs.numerator()?*?rhs.numerator(),?lhs.denominator()?*?rhs.denominator());
            }
            #endif

            int?main(void)
            {
            ???Rational
            int>?oneFourth(1,?4);
            ???Rational
            int>?result;
            ???result?
            =?oneFourth?*2;
            //..
            }

            當OPTION1為真時,就是item24中的實現(xiàn)方法:用非成員函數(shù)來使得所有的參數(shù)都可以接受類型轉換。
            但是編譯不能通過。這說明模板C++的世界是不一樣的: 對于以上代碼的非模板版本,編譯器只需要關心哪個函數(shù)可以調用就可以了;
            而引入模板后, 由于一個模板函數(shù)可以有無數(shù)個實例,編譯器首先要知道的是應該生成哪一個實例,然后才是調用。
            OPTION1為真時的代碼,這個模板函數(shù)在編譯時期就會碰到問題:模板參數(shù)無法確定。本來說好了接受一個Rational& 類型參數(shù)的,現(xiàn)在(在main()里 的第三行)給我一個int,叫我怎么辦?
            如果我是編譯器的話我會認為這種情況下模板參數(shù)T就是int,于是實例化下面的函數(shù)
            const?Rationalint>?operator?*?(?const?Rationalint>&?lhs,?const?Rationalint>&?rhs?);
            該函數(shù)可以通過隱式類型轉換接受int類型的參數(shù),順利完成任務!
            可是,編譯器很笨,做不到。

            于是可以考慮關掉OPTION1,打開OPTION2:把模板非成員函數(shù)當成友元+非成員+模板函數(shù)。為什么需要友元呢?
            OPTION1失敗的原因是編譯器無法生成合適的模板函數(shù)實例,它認為沒有合適的實例可以調用,于是編譯失敗。
            如果模板函數(shù)變成友元,編譯器首先看到有Rational對象定義出來(main()中第二第三行),就認為會有一個下面的函數(shù) 作為友元:
            const?Rationalint>?operator?*?(?const?Rationalint>&?lhs,?const?Rationalint>&?rhs?);
            當然,它不會在編譯階段去計較是不是真的有這么一個函數(shù)實例(友元嘛,就是朋友的東東,朋友說有,我就相信有咯~)
            于是,編譯通過!
            可是編譯通過后,鏈接卻出了問題:到鏈接階段才發(fā)現(xiàn),這個“朋友”的模板函數(shù)根本沒有實例可以調用!(還是一樣的問題, 沒有可以接受int參數(shù)的版本。朋友也不可靠啊……)
            問題就在類外部的友元模板函數(shù)僅僅在類中得到了聲明(declaration)而沒有被定義(definition)。對于模板函數(shù),使用者既需要聲明,又需要定義。(比如說 vector v,事實上已經通過制定模板參數(shù)完成了模板函數(shù)的定義。)

            于是終于到了最后一步:關掉OPTION1, OPTION2,打開OPTION3。
            無可奈何中我們把友元函數(shù)的定義放到了模板類的定義中,相當于把這個“朋友”拉上了船,只要我被定義了,你就一定會被定義。同甘共苦,才算是真的朋友@#¥%
            于是編譯通過了,因為編譯器看到了如下的函數(shù)被聲明
            const?Rationalint>?operator?*?(?const?Rationalint>&?lhs,?const?Rationalint>&?rhs?);
            于是鏈接通過了,因為隨著Rational對象的定義,上面的函數(shù)也實際被定義了出來,編譯器很高興,結果很完美。

            事實上這次的讀書筆記記了兩次,當我重新看第一次的筆記時竟然不知所云,于是重新看了一次,也修改了第一版的筆記成為 第二版。
            看來,模板真的很能搞……

            posted on 2010-05-01 11:53 Justin.H 閱讀(1709) 評論(0)  編輯 收藏 引用 所屬分類: Effective C++ 炒冷飯
            久久精品国产免费| 久久99国产精品尤物| 精品国产VA久久久久久久冰| 思思久久精品在热线热| 久久精品国产清高在天天线| 99久久久久| 亚洲国产精品成人AV无码久久综合影院 | 人妻无码αv中文字幕久久琪琪布| 亚洲级αV无码毛片久久精品| 国产成人久久精品麻豆一区| 亚洲国产精品综合久久一线| 久久久无码一区二区三区 | 午夜天堂精品久久久久| 国产成人无码精品久久久免费 | 成人精品一区二区久久久| 久久天天躁狠狠躁夜夜2020| 久久一日本道色综合久久| 久久久久国产亚洲AV麻豆| 久久精品国产精品青草app| 亚洲午夜久久久影院| 免费精品国产日韩热久久| 精品久久久久久无码专区不卡 | 久久亚洲高清观看| 亚洲AV无码久久精品蜜桃| 四虎亚洲国产成人久久精品| 久久精品国产WWW456C0M| 精品久久777| 99久久精品毛片免费播放| 丰满少妇高潮惨叫久久久| 九九精品久久久久久噜噜| 国产99久久久久久免费看 | 久久人人爽人人爽人人片AV东京热 | 久久久久久久亚洲精品 | 国产精品久久久久影院色| 久久亚洲精品无码AV红樱桃| 久久只这里是精品66| 久久人妻AV中文字幕| 伊人色综合久久天天网| 无码日韩人妻精品久久蜜桃| 区久久AAA片69亚洲| 亚洲午夜久久久久久久久电影网|