2011-03-20 77 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取消此警告。