如何在C ++中打印方法指针的地址?

时间:2011-03-20 06:46:00

标签: 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 *。

我需要的是一个方法指针的唯一标识符,我可以将其存储在容器中。我知道这听起来不错,但我正在开发一种可以从中受益的单元测试小玩具。我不担心方法的重载,我知道如何获得指向特定重载的指针。

我正在使用启用了C ++ 0x的g ++ 4.4.3。

如果您有任何疑问,请告诉我。

4 个答案:

答案 0 :(得分: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");

答案 1 :(得分: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的电话有点冗长 据推测,一些宏可能有助于简化它。

希望这有帮助

答案 2 :(得分:1)

如果只需要使用GCC,可以使用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进行编译以取消警告。

答案 3 :(得分:0)

没有可移植的方法来做到这一点。但你试过reinterpret_cast<void*>(p)吗?

我怀疑stream_print正在使用std::operator<<(std::ostream&, bool),因为这是指针到成员类型的唯一有效转换。这可以解释为什么你得到1

我不希望printf_print工作,即使编译器允许通过...传递指针到成员函数。我们无法保证sizeof(p) == sizeof(void*),这通常是获得va_arg“预期”非标准结果的实际最低要求。