2011-03-20 54 views
7

例如:如何在C++中打印方法指針的地址?

struct A { void m() { } }; 

void stream_print() { 
    void(A::*p)(void) = &A::m; 
    std::cerr << p << std::endl; 
} 

void printf_print() { 
    void(A::*p)(void) = &A::m; 
    fprintf(stderr, "%p", p); 
} 

的stream_print()函數始終打印 「1」,這顯然不是我想要的。 printf_print不會編譯,因爲p不能被轉換爲void *。

我需要的是我可以在一個容器中存儲的方法指針的唯一標識符。我知道這聽起來不是個好主意,但我正在開發一款可以從中受益的單元測試小玩具。我不擔心該方法的重載,我知道如何獲得指向特定超載的指針。

我使用G ++ 4.4.3用的C++ 0x啓用。

讓我知道如果您有任何疑問。

回答

9

成員函數指針通常是具有非平凡的內部結構的對象。這就是爲什麼你不能用打印原始類型的工具來打印它。將指針投射到void *不是可行的方法,因爲成員指針的大小通常大於sizeof(void *)。強制將它轉換爲void *將在任何情況下丟棄指針表示的一部分,從而不再保證唯一性。

如果你正在尋找的是從指針生成的唯一字符串,可以重新解釋指針爲一個字符陣列,並使用字符值的字符串表示該標識符中。喜歡的東西

void (A::*p)(void) = &A::m; 

for (size_t i = 0; i < sizeof p; ++i) 
    printf("%d ", reinterpret_cast<char *>(&p)[i]); 

printf("\n"); 
+0

+1除非有人指出瑕疵...... – 2011-03-20 08:04:06

+0

@Matthieu M .:首先,這顯然不正確。 C沒有定義函數指針到'void *'的轉換,當然,不能保證它。 C沒有定義數據指針和函數指針之間的「混合」轉換。你可以使用'void(*)(void)'作爲通用函數指針,但不能使用'void *'。 – AnT 2011-03-20 15:34:49

+0

@Matthieu M .:其次,問題是關於成員函數指針,而不是指向獨立函數的指針,這完全是另一回事。 – AnT 2011-03-20 15:35:33

0

還有就是要做到這一點沒有可移植的方法。但你有沒有試過reinterpret_cast<void*>(p)

我懷疑stream_print使用std::operator<<(std::ostream&, bool),因爲這是指向成員類型的唯一有效轉換。這將解釋你爲什麼得到1

我不希望printf_print工作,即使編譯器允許通過...傳遞指向成員函數。不保證sizeof(p) == sizeof(void*),這通常是從va_arg獲得「預期」非標準結果的實際最小值。

4

雖然我不是100%肯定我理解正確的問題,如果需要一些映射 從成員指針到一些獨特的ID,下面的代碼可能 達到目的:

struct A { 
    void f() {} 
    void g(int) {} 
}; 

template< class T, T > 
char* get_unique_id() { 
    static char dummy; 
    return &dummy; 
} 

int main() { 
    set< char* > s; 
    s.insert(get_unique_id< decltype(&A::f), &A::f >()); 
    s.insert(get_unique_id< decltype(&A::g), &A::g >()); 
    s.insert(get_unique_id< decltype(&A::f), &A::f >()); 
    s.insert(get_unique_id< decltype(&A::g), &A::g >()); 
    cout<< s.size() <<endl; // prints 2 
} 

get_unique_id的呼叫雖然有點冗長......
推測一些宏可能有助於簡化它。

希望這有助於

+0

這裏有一些模板參數推導要做的事情。好主意,但。 – 2011-03-20 11:59:10

+0

@亞歷山大:謝謝! **有事情要做** - 是的,可能是 'constexpr'?老實說,我不太熟悉0x。 – 2011-03-20 14:44:45

+0

不需要很多:'template char * get_unique_id(PMF pmf){static char dummy;返回&dummy;}'...'s.insert(get_unique_id(&A::f);)'。適用於任何類型,不只是指向成員函數的指針,但是你也可以使用'std :: type_info' – MSalters 2011-03-21 11:47:41

1

如果只需要與海灣合作委員會的工作,你可以使用this擴展到從指針到成員函數提取函數指針。

下面是一個例子:

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

struct A { void m() { } }; 

typedef void (*mptr)(A*); 

int main() 
{ 
    mptr p = (mptr)(&A::m); 
    std::cerr << (void*)p << std::endl; 
    fprintf(stderr, "%p\n", p); 
} 

編譯-Wno-pmf-conversions取消此警告。