• <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
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(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 閱讀(1065) 評論(0)  編輯 收藏 引用
            色欲综合久久躁天天躁| 久久99精品国产| 久久精品综合一区二区三区| 久久精品国产亚洲av日韩| 久久狠狠爱亚洲综合影院| 四虎国产精品成人免费久久| 亚洲一区精品伊人久久伊人| 色播久久人人爽人人爽人人片aV| 99精品久久久久久久婷婷| 久久狠狠色狠狠色综合| 久久精品视频网| 国产一区二区精品久久岳| 草草久久久无码国产专区| 久久成人精品| 伊人色综合久久天天网| 精品熟女少妇AV免费久久| 久久99国产乱子伦精品免费| 久久久久久久尹人综合网亚洲 | 好久久免费视频高清| 国内精品久久久久久久久| 久久亚洲精品成人av无码网站| 国产精品免费久久久久影院| 久久人爽人人爽人人片AV | 久久99热这里只有精品国产| 欧美日韩精品久久久免费观看| 漂亮人妻被中出中文字幕久久| 久久久久se色偷偷亚洲精品av | 久久成人永久免费播放| 精品久久久久久久久免费影院| 久久66热人妻偷产精品9| 国产成人AV综合久久| 久久亚洲国产精品成人AV秋霞| .精品久久久麻豆国产精品| 久久国产精品无码网站| 色8久久人人97超碰香蕉987| 久久这里只有精品首页| 久久久久久国产a免费观看黄色大片| 久久久亚洲欧洲日产国码aⅴ| 久久一区二区免费播放| 久久精品人人做人人爽电影| 久久精品无码一区二区WWW|