• <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年5月>
            262728293012
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(2)

            隨筆檔案

            友情鏈接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

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


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

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

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

            這里的用法是最常見的,跟普通的函數(shù)指針使用的地方也差不多。一般見到的地方也差不多都這么用。
            但成員函數(shù)指針還有更好用的地方,看下面這個例子
            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;
            }

            從這個例子看,成員函數(shù)指針也可以使用多態(tài)。看到這里是不是覺得成員函數(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
            到這里是不是會想到如何得到成員函數(shù)的地址呢?
            我想到最簡單的辦法就是輸出map文件,這樣就直接找到對應(yīng)的函數(shù)的地址。
            那運(yùn)行時候怎么得到呢?
            我的答案是沒有,
            如果是虛函數(shù)則可以通過搜索虛表來得到,不過這個方法太不通用,也很難實(shí)際應(yīng)用。算是一種理論上能,但不能實(shí)際應(yīng)用的方法。
            非虛函數(shù)的話,還不知道有什么好的方法能夠得到。

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

            新一篇: 如何寫易于使用的代碼 (一個宏引起的問題) | 舊一篇: 注冊COM到單獨(dú)用戶

            評論

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

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

            #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
            這個時候你如何輸出呢?12字節(jié)大小的指針?
            #healer_kx 發(fā)表于2009-01-20 19:49:41  IP: 125.33.137.*
            你們兩個真無聊,我都開始研究JS了
            #zenny_chen 發(fā)表于2009-01-20 20:22:15  IP: 218.242.128.*
            哈哈,healer_kx兄挺與時俱進(jìn)的嘛。

            呵呵,雖然沒用過CodeGear,但不管是基于怎樣的處理器都可以獲得指針值吧。只要匹配好地址類型就行。我剛才就是忘了說前提了。實(shí)際上如果要考慮到兼容性的話就將地址類型大小指明一下就行啊。
            #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的匯編形式,不過我這里就再借助一下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很專業(yè)

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

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

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

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


            色综合久久综精品| 久久久久青草线蕉综合超碰| 国产美女久久精品香蕉69| 无码伊人66久久大杳蕉网站谷歌| 久久久久久国产精品无码超碰| 久久99精品久久久久久| 精品久久久久久无码国产| 亚洲精品乱码久久久久久| 国产成人精品久久二区二区| 婷婷久久精品国产| 久久青青草原精品影院| 一本一道久久综合狠狠老| 国产免费久久精品丫丫| 亚洲αv久久久噜噜噜噜噜| 国产精品亚洲综合专区片高清久久久 | 99久久99久久精品国产| 精品久久久久久久国产潘金莲| 精品国产VA久久久久久久冰| 久久婷婷人人澡人人| 久久精品国产一区二区三区日韩| 亚洲色欲久久久久综合网| 91精品国产91久久久久久青草| 午夜久久久久久禁播电影| 香蕉久久久久久狠狠色| 久久久久噜噜噜亚洲熟女综合 | 伊人久久大香线蕉成人| 久久久噜噜噜久久| 国产精自产拍久久久久久蜜| 秋霞久久国产精品电影院| 国产精品一久久香蕉国产线看观看| 综合久久精品色| 亚洲国产婷婷香蕉久久久久久| 国内精品免费久久影院| 爱做久久久久久| 久久综合精品国产一区二区三区| 国产精久久一区二区三区| 精品久久久久久久久久中文字幕| 国产精品热久久无码av| 久久久久久一区国产精品| 日韩十八禁一区二区久久| 精品久久久久久久久免费影院|