• <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>
            隨筆 - 13  文章 - 36  trackbacks - 0
            <2009年3月>
            22232425262728
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            常用鏈接

            留言簿(2)

            隨筆檔案

            友情鏈接

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

             轉(zhuǎn)載自:http://blog.csdn.net/akirya/archive/2009/01/18/3825040.aspx


            很多人對(duì)成員函數(shù)指針有無(wú)解,以為成員函數(shù)指針同普通的函數(shù)指針區(qū)別不大,多了一個(gè)參數(shù).
            然而實(shí)際上卻不是.多了個(gè)參數(shù),是不假,但他確實(shí)不是指針,雖說(shuō)名字中有指針兩個(gè)字,但實(shí)際上卻不是指針.
            先看看最簡(jiǎn)單的使用

            class test
            {
            public:
             void func(){printf("call test::func\n");};
            };

            int main()
            {
             void(test::*p)() = &test::func;
             test x;
             (x.*p)();
            }

            這里的用法是最常見(jiàn)的,跟普通的函數(shù)指針使用的地方也差不多。一般見(jiàn)到的地方也差不多都這么用。
            但成員函數(shù)指針還有更好用的地方,看下面這個(gè)例子
            class base
            {
            public:
             virtual void func(){printf("call base::func\n");};
            };
            class test:public base
            {
            public:
             void func(){printf("call test::func\n");};
            };

            int main()
            {
             void(base::*p)() = &base::func;
             test x;
             (x.*p)();//調(diào)用的是test::func;
             base y;
             (y.*p)();//調(diào)用的是base::func;
            }

            從這個(gè)例子看,成員函數(shù)指針也可以使用多態(tài)。看到這里是不是覺(jué)得成員函數(shù)指針跟之前想的不一樣?

            緊接著上面的例子,只更改main函數(shù)的內(nèi)容

            int main()
            {
             void(base::*p)() = &base::func;
             printf("sizeof( void(base::*p)()) %d\n" , sizeof(p) );
            };


            這里的輸出結(jié)果能想到么?(我的系統(tǒng)是32位的XP)
            VC9 下是 4
            GCC4.2.1 是 8
            CodeGear C++ 6.10 的結(jié)果是12
            到這里是不是會(huì)想到如何得到成員函數(shù)的地址呢?
            我想到最簡(jiǎn)單的辦法就是輸出map文件,這樣就直接找到對(duì)應(yīng)的函數(shù)的地址。
            那運(yùn)行時(shí)候怎么得到呢?
            我的答案是沒(méi)有,
            如果是虛函數(shù)則可以通過(guò)搜索虛表來(lái)得到,不過(guò)這個(gè)方法太不通用,也很難實(shí)際應(yīng)用。算是一種理論上能,但不能實(shí)際應(yīng)用的方法。
            非虛函數(shù)的話(huà),還不知道有什么好的方法能夠得到。

            發(fā)表于 @ 2009年01月18日 10:19:00|評(píng)論(loading... )|收藏

            新一篇: 如何寫(xiě)易于使用的代碼 (一個(gè)宏引起的問(wèn)題) | 舊一篇: 注冊(cè)COM到單獨(dú)用戶(hù)

            評(píng)論

            #taodm 發(fā)表于2009-01-19 15:12:59  IP: 10.63.110.*
            C++語(yǔ)言當(dāng)初設(shè)計(jì)的時(shí)候就認(rèn)為你不需要得到它的真正地址。
            #taodm 發(fā)表于2009-01-20 15:09:58  IP: 10.63.110.*
            C++在設(shè)計(jì)的時(shí)候就認(rèn)為不(應(yīng)該)需要獲得成員函數(shù)的真實(shí)地址。
            解決方案對(duì)你來(lái)說(shuō)只是舉手之勞。
            #akirya 發(fā)表于2009-01-20 18:43:34  IP: 58.30.180.*
            呵呵~taodm 見(jiàn)笑了:D
            最初這個(gè)問(wèn)題就是因?yàn)槟阄也湃ヅ靼椎?/dd>
            #zenny_chen 發(fā)表于2009-01-20 18:58:09  IP: 218.242.128.*
            akirya大俠似乎沒(méi)有解釋成員函數(shù)指針為何不是指針,難道它屬于別的什么東西?不過(guò)本人倒是覺(jué)得它應(yīng)該算是指針吧。它具有指針的基本特性啊,呵呵。

            另外,關(guān)于通過(guò)成員函數(shù)指針來(lái)獲得成員函數(shù)地址的方法確實(shí)比較困難。它的困難點(diǎn)在于必須繞過(guò)C++編譯器的類(lèi)型檢查。像VC對(duì)成員函數(shù)指針類(lèi)型檢查的很?chē)?yán),即使是void*類(lèi)型都不能轉(zhuǎn),也無(wú)法通過(guò)reinterpret_cast、dynamic_cast之類(lèi)的來(lái)轉(zhuǎn)。
            因此我這里將采取暴力手段來(lái)獲取:

            #include <iostream>
            using namespace std;


            class Test
            {
            public:

            void Hello(void)
            {
            cout << "Hello, world!" << endl;
            }

            void Hello(int i)
            {
            cout << "The answer is: " << i << endl;
            }
            };


            template <typename T>
            inline unsigned GetMemberFuncAddress(T p)
            {
            unsigned result;

            __asm
            {
            mov eax, dword ptr [p]
            mov dword ptr [result], eax
            }

            return result;
            }


            int main(void)
            {
            void (Test::* p)(void) = &Test::Hello;
            void (Test::* q)(int) = &Test::Hello;

            (Test().*p)();
            (Test().*q)(100);

            cout << "The address is: " << p << endl;
            cout << "The address is: " << q << endl;

            cout << "The address is: 0x" << hex << GetMemberFuncAddress(p) << endl;
            cout << "The address is: 0x" << hex << GetMemberFuncAddress(q) << endl;

            return 0;
            }
            #akirya 發(fā)表于2009-01-20 19:28:46  IP: 58.30.180.*
            很遺憾,VC不代表C++

            CodeGear C++ 6.10 下 sizeof(成員指針大小)結(jié)果是12
            這個(gè)時(shí)候你如何輸出呢?12字節(jié)大小的指針?
            #healer_kx 發(fā)表于2009-01-20 19:49:41  IP: 125.33.137.*
            你們兩個(gè)真無(wú)聊,我都開(kāi)始研究JS了
            #zenny_chen 發(fā)表于2009-01-20 20:22:15  IP: 218.242.128.*
            哈哈,healer_kx兄挺與時(shí)俱進(jìn)的嘛。

            呵呵,雖然沒(méi)用過(guò)CodeGear,但不管是基于怎樣的處理器都可以獲得指針值吧。只要匹配好地址類(lèi)型就行。我剛才就是忘了說(shuō)前提了。實(shí)際上如果要考慮到兼容性的話(huà)就將地址類(lèi)型大小指明一下就行啊。
            #ifdef ADDRESS_32BIT
            typedef unsigned TYPE_ADDRESS;
            #elif defined(ADDRESS_64BIT)
            typedef unsigned long long TYPE_ADDRESS;
            #elif defined(ADDRESS_96BIT)
            typedef struct
            {
            unsigned low4;
            unsigned mid4;
            unsigned high4;
            }TYPE_ADDRESS;
            #endif

            雖然我不知道CodeGear的匯編形式,不過(guò)我這里就再借助一下MASM了,呵呵:

            template <typename T>
            inline TYPE_ADDRESS GetMemberFuncAddress(T p)
            {
            TYPE_ADDRESS result;

            #ifdef ADDRESS_32BIT
            #define WORD_SIZE dword
            #define MOV_FORM mov
            #define REG_OPT eax
            #elif defined(ADDRESS_64BIT)
            #define WORD_SIZE mmword
            #define MOV_FORM movq
            #define REG_OPT mm0
            #elif defined(ADDRESS_96BIT)
            #define WORD_SIZE xmmword
            #define MOV_FORM movdqu
            #define REG_OPT xmm0
            #endif

            __asm
            {
            MOV_FORM REG_OPT, WORD_SIZE ptr [p]
            MOV_FORM WORD_SIZE ptr [result], REG_OPT
            }

            return result;
            }
            #akirya 發(fā)表于2009-01-20 22:16:25  IP: 58.30.180.*
            zenny_chen很專(zhuān)業(yè)

            那假如是指針的話(huà),那多態(tài)例子怎么解釋?zhuān)瑢?duì)象不同調(diào)用的函數(shù)也就不用? 但成員函數(shù)函數(shù)指針的值并沒(méi)有改變。
            #zenny_chen 發(fā)表于2009-01-20 23:33:34  IP: 116.234.182.*
            呵呵,如果是虛函數(shù)的話(huà)這樣整肯定不行了。而且每種編譯器對(duì)于對(duì)象模型模型可能建的不一樣,而且虛函數(shù)表的建立機(jī)制也可能大相徑庭,所以訪(fǎng)問(wèn)虛函數(shù)指針的值的方式也會(huì)不同。
            我上面僅僅是針對(duì)你最后一句話(huà)的回答,呵呵。
            #akirya 發(fā)表于2009-01-20 23:54:32  IP: 58.30.180.*
            的確不是指針,在CodeGear C++ 6.10(也就是BCB的后續(xù)版本)存的是一個(gè)偏移量.
            sizeof( 成員函數(shù)指針)大小是12也就說(shuō)明了指針這種假設(shè)是不成立的,具體存的是取決與編譯器的實(shí)現(xiàn)。

            標(biāo)準(zhǔn)也沒(méi)有對(duì)成員函數(shù)指針里面存的是啥東西做規(guī)定了,我寫(xiě)這個(gè)目的就是說(shuō)明一下,成員函數(shù)指針不是真正的指針,里面保存的不一定是地址。
            #taodm 發(fā)表于2009-01-21 09:45:21  IP: 10.63.110.*
            又有匯編高手冒出來(lái)了。接著又要探討獲取構(gòu)造函數(shù)、析構(gòu)函數(shù)真實(shí)地址的暴力手法了。。。。。。
            #zenny_chen 發(fā)表于2009-01-21 13:31:21  IP: 218.242.128.*
            哈哈,taodm真是搞笑啊。

            嗯……如果是虛成員函數(shù)的話(huà)其地址是虛的嘛。所以拿到的函數(shù)地址可以認(rèn)為是“虛指針”,呵呵。而且編譯器可以在編譯時(shí)斷定對(duì)象所調(diào)用的函數(shù)是否為虛函數(shù),對(duì)象是否具有虛函數(shù)表指針。所以這些在編譯時(shí)就搞定的東西即使用暴力手段也難以獲取,呵呵。
            我想說(shuō)的是“虛指針”算是一種特殊的指針罷。
            posted on 2009-03-18 11:06 Alex-Lee 閱讀(1067) 評(píng)論(0)  編輯 收藏 引用

            只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            国产一级持黄大片99久久| 99久久精品无码一区二区毛片| 久久国产福利免费| 国产精品久久久久久久久久影院 | 亚洲精品无码久久久久AV麻豆| 亚洲国产一成久久精品国产成人综合| 久久精品国产99国产精品导航| 久久r热这里有精品视频| 午夜精品久久久久| 亚洲伊人久久大香线蕉苏妲己| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 久久精品国产亚洲av水果派| 国产精品久久久久无码av| 久久久久亚洲AV无码专区桃色| 亚洲va久久久噜噜噜久久天堂| 国产成人综合久久精品尤物| 久久婷婷五月综合97色直播| 久久国产成人精品麻豆| 99蜜桃臀久久久欧美精品网站| 久久婷婷久久一区二区三区| 色欲久久久天天天综合网| 久久人人爽人爽人人爽av | 亚洲人成精品久久久久| 久久亚洲电影| 九九热久久免费视频| 亚洲国产成人久久综合一 | 久久99热精品| 国产精品久久久久久吹潮| 新狼窝色AV性久久久久久| 波多野结衣久久| 中文字幕热久久久久久久| 久久精品免费全国观看国产| 久久综合视频网站| 色综合合久久天天给综看| 久久亚洲视频| 久久亚洲精品无码aⅴ大香| 三级三级久久三级久久| 精产国品久久一二三产区区别| 午夜视频久久久久一区 | 日韩精品久久无码中文字幕| 久久久久高潮综合影院|