2012-08-10 35 views
2

我寫了一些測試代碼,找出有關成員函數的地址。但結果讓我困惑。代碼是指針到成員函數的地址是什麼,沒有虛擬也沒有繼承

#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 

class A 
{ 
public: 
     A(char _a, char _b, char _c, char _t):a(_a), b(_b), c(_c), t(_t){} 

private: 
     char t; 
     char a; 
public: 
     char b; 
     char c; 
     void test1(){std::cout << a << std::endl;} 
     void test2(){std::cout << b << std::endl;} 
     void test3(){std::cout << c << std::endl;} 
     void test4(){std::cout << t << std::endl;} 

     static void print(){ 

       char A::*pa = &A::a; 
       char A::*pb = &A::b; 
       char A::*pc = &A::c; 
       char A::*pt = &A::t; 
       printf("data member : %p, %p, %p, %p\n", pa, pb, pc, pt); 

       void (A::*pf1)() = &A::test3; 
       void (A::*pf2)() = &A::test2; 
       void (A::*pf3)() = &A::test3; 
       void (A::*pf4)() = &A::test2; 
       printf("function member : %p, %p, %p, %p\n", pf1, pf2, pf3, pf4); 
     } 
}; 

int main() 
{ 
     A::print(); 

    //system("pause");//need on Dev-c++ 
     return 0; 
} 

我運行ubuntu上與g ++以及WINDOS與開發 - C++此代碼,結果是相同的

data member : 0x1, 0x2, 0x3, (nil) 
function member : 0x8048780, (nil), 0x804874e, (nil) 

爲什麼PF2和PF4是nil?

+0

你使用編譯器優化嗎? – klm123 2012-08-10 02:48:30

+4

[指向成員函數是非常奇怪的動物](http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspx)。 – 2012-08-10 02:57:19

回答

3

指向成員的指針不是常規指針,可以通過打印指向成員的指針的大小和常規指針的大小來測試它。你所擁有的代碼表現出未定義的行爲,但如果你想簡單地解釋結果,printf需要可變數量的參數,這是通過按照某種預先設定的順序將參數推入堆棧並添加一些額外信息通話中參數的數量是。

在你的情況下,指針 - 成員函數被按原樣(通常是常規指針大小的兩倍),然後printf正在讀取堆棧並將其中的位解釋爲常規指針。我的猜測(你必須閱讀編譯器/平臺文檔來驗證這一點)是,你只打印前兩個參數,內容用逗號分隔。

稍微好一點的方法是創建一個指向成員函數的指針和適當大小的char數組的聯合,使用指向成員的指針初始化它並通過數組打印十六進制值。

2

爲什麼pf2和pf4是零?

因爲顯示的代碼有未定義的行爲。指向成員函數are not pointers(是的,是的,我知道這是錯誤的命名;這是C++),但printf格式字符串正在等待指針。