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

            隨筆檔案

            友情鏈接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             轉載自:http://blog.csdn.net/akirya/archive/2009/01/18/3825040.aspx


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

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

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

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

            從這個例子看,成員函數指針也可以使用多態。看到這里是不是覺得成員函數指針跟之前想的不一樣?

            緊接著上面的例子,只更改main函數的內容

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


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

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

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

            評論

            #taodm 發表于2009-01-19 15:12:59  IP: 10.63.110.*
            C++語言當初設計的時候就認為你不需要得到它的真正地址。
            #taodm 發表于2009-01-20 15:09:58  IP: 10.63.110.*
            C++在設計的時候就認為不(應該)需要獲得成員函數的真實地址。
            解決方案對你來說只是舉手之勞。
            #akirya 發表于2009-01-20 18:43:34  IP: 58.30.180.*
            呵呵~taodm 見笑了:D
            最初這個問題就是因為你我才去弄明白的
            #zenny_chen 發表于2009-01-20 18:58:09  IP: 218.242.128.*
            akirya大俠似乎沒有解釋成員函數指針為何不是指針,難道它屬于別的什么東西?不過本人倒是覺得它應該算是指針吧。它具有指針的基本特性啊,呵呵。

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

            #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 發表于2009-01-20 19:28:46  IP: 58.30.180.*
            很遺憾,VC不代表C++

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

            呵呵,雖然沒用過CodeGear,但不管是基于怎樣的處理器都可以獲得指針值吧。只要匹配好地址類型就行。我剛才就是忘了說前提了。實際上如果要考慮到兼容性的話就將地址類型大小指明一下就行啊。
            #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 發表于2009-01-20 22:16:25  IP: 58.30.180.*
            zenny_chen很專業

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

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

            嗯……如果是虛成員函數的話其地址是虛的嘛。所以拿到的函數地址可以認為是“虛指針”,呵呵。而且編譯器可以在編譯時斷定對象所調用的函數是否為虛函數,對象是否具有虛函數表指針。所以這些在編譯時就搞定的東西即使用暴力手段也難以獲取,呵呵。
            我想說的是“虛指針”算是一種特殊的指針罷。
            posted on 2009-03-18 11:06 Alex-Lee 閱讀(1064) 評論(0)  編輯 收藏 引用
            性做久久久久久久久老女人| 久久久久久a亚洲欧洲aⅴ | 婷婷久久久亚洲欧洲日产国码AV| 婷婷久久综合九色综合九七| 欧美激情一区二区久久久| 波多野结衣中文字幕久久| 国产视频久久| 久久精品人人槡人妻人人玩AV | 久久久久亚洲av成人网人人软件| 久久久久se色偷偷亚洲精品av| 久久人人妻人人爽人人爽| 久久久久亚洲爆乳少妇无| 久久国产免费直播| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久久精品日本一区二区三区| 伊人久久精品无码二区麻豆| 天天久久狠狠色综合| 亚洲人成网亚洲欧洲无码久久| 91久久国产视频| 精品久久久久久无码专区不卡| 思思久久99热免费精品6| 99久久国产亚洲高清观看2024| 久久99热只有频精品8| 无码国内精品久久人妻麻豆按摩| 久久99精品久久久久久 | 久久中文字幕一区二区| 亚洲精品无码久久久影院相关影片| 久久精品国产亚洲一区二区三区| 国产精品美女久久久| 亚洲精品乱码久久久久久自慰| yy6080久久| 久久国产亚洲精品| 亚洲日韩欧美一区久久久久我 | 国内精品久久久久国产盗摄| 国内精品伊人久久久久| 国产午夜福利精品久久2021| 国产V综合V亚洲欧美久久| 99久久er这里只有精品18| 2021久久精品国产99国产精品| 久久精品国产2020| 亚洲国产精品无码久久SM|