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


            蜜桃麻豆www久久| 亚洲中文字幕无码久久综合网| 国内精品久久久人妻中文字幕| 久久天天躁狠狠躁夜夜躁2O2O| 久久精品一区二区三区不卡| 久久久久国产视频电影| 日韩欧美亚洲综合久久 | 国产巨作麻豆欧美亚洲综合久久| 久久久久国产视频电影| 欧美一区二区三区久久综| 天天爽天天爽天天片a久久网| 亚洲国产成人久久精品99 | 久久久国产精华液| 久久婷婷综合中文字幕| 久久人人爽人人人人片av| 国产精品久久久久乳精品爆| 国产69精品久久久久9999APGF| 国产成人精品久久二区二区| 无码国内精品久久综合88 | 精品久久久久久国产91| 思思久久精品在热线热| 久久毛片免费看一区二区三区| 久久精品人人做人人爽电影蜜月| 久久久久亚洲av毛片大| 婷婷久久综合九色综合98| 久久夜色精品国产欧美乱| 国产精品美女久久福利网站| 久久毛片免费看一区二区三区| 99久久综合狠狠综合久久止| av色综合久久天堂av色综合在 | 久久久久久久97| 一本色道久久HEZYO无码| 亚洲婷婷国产精品电影人久久| 国产精品成人99久久久久| 国产免费久久精品丫丫| 日本久久久精品中文字幕| 66精品综合久久久久久久| 欧美久久综合性欧美| 国产综合成人久久大片91| 精品久久久久中文字幕一区| 久久免费精品一区二区|