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

            cexer

            cexer
            posts - 12, comments - 334, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            更好地仿真VC++關(guān)鍵字__uuidof

            Posted on 2008-07-05 20:58 cexer 閱讀(2790) 評(píng)論(8)  編輯 收藏 引用 所屬分類: utility

            轉(zhuǎn)帖請(qǐng)注明出處 http://www.shnenglu.com/cexer/archive/2008/07/05/55419.html

              世界上有個(gè)叫__uuidof的關(guān)鍵字。這是一個(gè)家喻戶曉且其被廣泛使用的關(guān)鍵字,幾乎可以說,有COM程序員的地方,就有它 __uuidof的存在。其很好很強(qiáng)大的程度是人所共見的,夸張一點(diǎn)比喻:離開它的COM程序員,就像失去了點(diǎn)火器的火箭,雖然可以人工點(diǎn)火,但是不安全且無效率。

              不過很多人并不知道,這其實(shí)是一個(gè)編譯器擴(kuò)展關(guān)鍵字,提供了此關(guān)鍵字的僅VC一家別無它店。幸運(yùn)的是,強(qiáng)大的C++讓我們能夠輕易仿真出這個(gè)關(guān)鍵字的大部分功能。

              網(wǎng)上能夠找到一種仿真的方法,見許式偉:《仿真VC++提供的關(guān)鍵字__uuidof》。該方法的實(shí)現(xiàn)是:特化模板類的成員函數(shù),然后運(yùn)行時(shí)調(diào)用函數(shù)根據(jù)UUID字符串產(chǎn)生出UUID,由于是生成于運(yùn)行時(shí),所以它無可避免地有兩個(gè)缺點(diǎn):

            • 存在運(yùn)行時(shí)消耗。
            • 無法作為非類型模板參數(shù)傳遞給模板。

              那些整天流著口水追求效率的C++程序員們,是不能忍受任何不必要的運(yùn)行時(shí)消耗的。對(duì)于第二點(diǎn),VC的關(guān)鍵字__uuidof取出來的UUID是能夠作為非類型模板參數(shù)傳遞的,ATL中就大量地使用了這樣的參數(shù)傳遞形式,所以目前的這種實(shí)現(xiàn)功能有限,仿真度還不夠高。

              其實(shí)只要能讓它能夠編譯期決定UUID的值,那么這兩個(gè)問題就迎刃而解了。而這是肯定可以實(shí)現(xiàn)的,并且很簡(jiǎn)單。我曾經(jīng)在自己寫的一個(gè)COM庫(kù)里實(shí)現(xiàn)過這樣的方法,雖然那個(gè)庫(kù)已經(jīng)不知丟到哪里去了,不過那個(gè)方法還記得。

              解決的途徑還是離不開模板特化。類的成員包括成員函數(shù)和成員變量,函數(shù)是運(yùn)行時(shí)作用的,然而static const的成員變量可以是編譯期就決定。所以解決的方法就在眼前了:特化模板的成員變量。

              以下是我的實(shí)現(xiàn)方法。

              先定義一個(gè)類模板,它有一個(gè)static const ,UUID類型的成員變量:

                template<typename T>   
            struct _uuid_of_impl
            {
            static const UUID id;
            };
            template<typename T>
            const UUID _uuid_of_impl<T>::id=GUID_NULL;

              有了這個(gè)簡(jiǎn)單的東西就好辦了,只需要針對(duì)某個(gè)接口特它的成員變量就行了,如:

                template<>    
            const UUID _uuid_of_impl<IUnknown>::id=IID_IUnknown;

            template<>
            const UUID _uuid_of_impl<IDispatch>::id=IID_IDispatch;

            
            


              然后我們就可以這樣取得接口的UUID:

                IID IunknownID=_uuid_of_impl<IUnknown>::id;   
            IID IdispatchID=_uuid_of_impl<IDispatch>::id;


              作為非類型模板參數(shù)傳遞:

                template<const IID* t_iid>   
            struct __uuid_of_test
            {
            __uuid_of_test()
            {}

            void test()
            {
            t_iid;
            }
            };

            __uuid_of_test<&(_uuid_of_impl<IDispatch>::id) > obj;


              不過現(xiàn)在這種實(shí)現(xiàn)還有一些問題,看以下代碼:

                IID ITypelibID=_uuid_of_impl<ITypeLib>::id;


              注意我們并沒有事先對(duì)模板__uuid_of_impl特化ITypeLib的版本。但是以上語(yǔ)句卻能夠編譯通過,在運(yùn)行時(shí),__uuid_of_impl<ITypeLib>的值將會(huì)是錯(cuò)誤的值GUID_NULL。這是因?yàn)椋覀兌x模板的時(shí)候,同時(shí)在模板外定義了模板的靜態(tài)成員變量并賦值為GUID_NULL,所以沒有用特化的方法定義UUID的接口,都將使用GUID_NULL這個(gè)通用值。這當(dāng)然不是我們想要的。所以我們想在沒有定義UUID的時(shí)候讓編譯器警告我們,要達(dá)到這樣的效果只需要去掉上面那句:

                template<typename T>   
            const UUID _uuid_of_impl<T>::id=GUID_NULL;


              現(xiàn)在再進(jìn)行編譯,編譯器會(huì)告訴你,有一個(gè)無法解析的符號(hào)。根據(jù)編譯器提供的相關(guān)信息,很容易就能確定問題所在。這樣能夠在編譯期極大地減小安全隱患。

              最后加上我們定義的幾個(gè)宏,這是最后的全部實(shí)現(xiàn):

                template<typename T>   
            struct _uuid_of_impl
            {
            static const UUID id;
            };

            #define uuid_of(x) _uuid_of_impl<x>::id
            #define DEFINE_UUID(x,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
            template<> \
            const UUID _uuid_of_impl<x>::id={l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}


              用以下代碼測(cè)試通過:

                struct ITest{};   

            DEFINE_UUID(ITest,0x96289151,0xf059,0x4049,0x88,0x19,0x61,0xa6,0xe9,0x79,0xc,0xf1);

            template<const IID* t_iid>
            struct uuid_of_test
            {
            uuid_of_test(){}
            };

            int main()
            {
            IID xxxxID=uuid_of(ITest);
            uuid_of_test<&(uuid_of(ITest))> obj;

            return 0;
            }


              需要注意的是DEFINE_UUID應(yīng)該在實(shí)現(xiàn)文件(*.cpp,*.cxx,……)當(dāng)中使用。到這里,仍有一些使用方法與VC的關(guān)鍵字是不一樣的,所以仍沒做到仿真度100%。不過我相信通過預(yù)處理元編程,能夠相當(dāng)程度地逼近它,只是我對(duì)預(yù)處理元編程不是很了解,所以就不在這里獻(xiàn)丑了。

            Feedback

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 02:15 by 放屁啊狗
            我感覺ms的com快走向末路了,沒有啥創(chuàng)新。ms走的就是自我封閉,自戀、自殘的路線

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 05:33 by www.helpsoff.com.cn
            好不容易在cppblog.com看到一篇真正的技術(shù)文章,不過看到的回復(fù)又實(shí)在讓人如鯁在喉。“放屁阿狗”仁兄,君不知COM的技術(shù)和概念是多少現(xiàn)在所謂前沿技術(shù)和概念的基礎(chǔ),不知道是在睜眼說瞎話還是在這里說反話吸引眼球?

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 09:51 by 空明流轉(zhuǎn)
            @www.helpsoff.com.cn
            這里技術(shù)文章也不少了。。。為什么叫真正的?
            boost上有一個(gè)uuid的實(shí)現(xiàn)好像。
            還有COM,這個(gè)東西確實(shí)很繁雜,但是概念上沒什么問題,就是實(shí)現(xiàn)很拖沓。

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 09:55 by pang
            你好 我是出版社的編輯,我看到你博客中的內(nèi)容,感覺寫的非常好,如果想把這些內(nèi)容

            和更多的人分享,可以和我聯(lián)系,把這些東西寫成書。
            我的郵箱:books_522008@yahoo.com.cn
            或者加我的MSN:pyq_19852008@hotmail.com

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 10:38 by toperray
            看看ADOBE、firefox等等的基礎(chǔ)技術(shù)吧,com消亡了?

            沒有,而且越來越多的被采用。

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 12:17 by cexer
            # re: 更好地仿真VC++關(guān)鍵字__uuidof 回復(fù) 更多評(píng)論 刪除評(píng)論
            2008-07-06 02:15 by 放屁啊狗
            我感覺ms的com快走向末路了,沒有啥創(chuàng)新。ms走的就是自我封閉,自戀、自殘的路線


            Microsoft的技術(shù)從剛誕生的時(shí)候,會(huì)被人認(rèn)定要不幸夭亡。當(dāng)它成長(zhǎng)成熟起來的時(shí)候,又會(huì)被認(rèn)定在新技術(shù)四面夾擊的情況下必定被淘汰。但是事實(shí)證明了,那些擔(dān)憂都是多余的嘛,現(xiàn)在微軟的COM還是軟件組件模型的最廣泛實(shí)現(xiàn)和應(yīng)用的方式。我相反覺得,微軟走的路線并不是封閉自戀,而是學(xué)習(xí)各家所長(zhǎng)并融匯到自己的技術(shù)里。

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 12:23 by cexer
            謝謝上面回復(fù)的www.helpsoff.com.cn,我這個(gè)就是一點(diǎn)小技巧,還真說不上是“技術(shù)”。謝謝你的支持,我會(huì)努力的。

            謝謝pang,謝謝支持。

            # re: 更好地仿真VC++關(guān)鍵字__uuidof  回復(fù)  更多評(píng)論   

            2008-07-06 15:45 by www.helpsoff.com.cn
            回空明流轉(zhuǎn),因?yàn)榻?jīng)常在cppblog上看到聊面試的,又有進(jìn)而聊面試過程的,然后又進(jìn)而有聊自己如何管理別人的...所以一看到這篇有思考過程有代碼的文章,禁不住說“真正的”,哈哈,見諒見諒...
            久久综合九色综合欧美狠狠| 久久久噜噜噜久久中文字幕色伊伊 | 久久精品亚洲福利| 国产激情久久久久影院小草| 色综合久久久久网| 久久精品国产亚洲av高清漫画| 久久精品无码午夜福利理论片| 久久久久久伊人高潮影院| 一本久久免费视频| 少妇精品久久久一区二区三区 | 婷婷伊人久久大香线蕉AV| 波多野结衣AV无码久久一区| 久久97精品久久久久久久不卡 | 亚洲国产精品一区二区久久| 欧美午夜精品久久久久久浪潮| 伊人久久无码精品中文字幕| 伊色综合久久之综合久久| 国内精品久久人妻互换| 久久久国产视频| 99国产欧美久久久精品蜜芽| 亚洲国产成人乱码精品女人久久久不卡| 久久免费香蕉视频| 久久亚洲国产中v天仙www | 国产韩国精品一区二区三区久久| 久久精品国产亚洲综合色| 欧美日韩精品久久久久| 性高湖久久久久久久久| 99久久夜色精品国产网站| 久久亚洲AV无码精品色午夜| 国产免费福利体检区久久 | 亚洲AV成人无码久久精品老人| 久久久久久久人妻无码中文字幕爆| 久久香蕉国产线看观看99| 亚洲天堂久久久| 日韩一区二区久久久久久| 亚洲国产视频久久| 国产女人aaa级久久久级| 亚洲熟妇无码另类久久久| 久久久久99精品成人片三人毛片 | 欧洲人妻丰满av无码久久不卡| 久久久国产99久久国产一|