如何在C++中打印成员函数地址

EFa*_*nZh 13 c++ pointers function-pointers pointer-to-member

它看起来像std::cout无法打印成员函数的地址,例如:

#include <iostream>

using std::cout;
using std::endl;

class TestClass
{
  void MyFunc(void);

public:
  void PrintMyFuncAddress(void);
};

void TestClass::MyFunc(void)
{
  return;
}

void TestClass::PrintMyFuncAddress(void)
{
  printf("%p\n", &TestClass::MyFunc);
  cout << &TestClass::MyFunc << endl;
}

int main(void)
{
  TestClass a;

  a.PrintMyFuncAddress();

  return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

结果是这样的:

003111DB
1
Run Code Online (Sandbox Code Playgroud)

如何MyFunc使用打印地址std::cout

tem*_*def 16

我不相信这种语言提供了任何设施.operator <<流有重载打印正常void*指针,但成员函数指针不能转换为void*s.这是特定于实现的,但通常成员函数指针实现为一对值 - 指示成员函数是否为虚拟的标志,以及一些额外数据.如果该函数是非虚函数,则该额外信息通常是实际成员函数的地址.如果函数是虚函数,则该额外信息可能包含有关如何索引到虚函数表以查找给定接收器对象的函数的数据.

一般来说,我认为这意味着在不调用未定义的行为的情况下打印成员函数的地址是不可能的.您可能必须使用一些特定于编译器的技巧来实现此效果.

希望这可以帮助!


Pan*_*sis 13

我想补充其他答案,你打印'1'而不是地址的原因是,由于某种原因,编译器将你的函数指针强制转换为布尔值,所以你真的调用 ostream& operator<< (bool val);

这似乎与作为成员函数的函数无关.

您可以使用clang ++ -cc1 -ast-dump发现此类信息:

(ImplicitCastExpr 0x3861dc0 <col:13, col:25> '_Bool' <MemberPointerToBoolean>
    (UnaryOperator 0x3861940 <col:13, col:25> 'void (class TestClass::*)(void)' prefix '&'
        (DeclRefExpr 0x38618d0 <col:14, col:25> 'void (void)' CXXMethod 0x3861500 'MyFunc' 'void (void)')))))
Run Code Online (Sandbox Code Playgroud)


Mr.*_*bis 5

一种方法是(我不确定它是否可移植):

void TestClass::PrintMyFuncAddress(void)
{
  void (TestClass::* ptrtofn)() = &TestClass::MyFunc;
  cout << (void*&)ptrtofn<< endl;
}
Run Code Online (Sandbox Code Playgroud)

工作示例:http://ideone.com/1SmjW

  • 该计划表现得很少.这种C风格的强制转换是一种`reinterpret_cast`,通常只是将内存重新解释为目标类型.在这种情况下,它将使用指向成员的指针中存储的第一个`sizeof(void*)`字节,就好像它是一个`void*`,但是如果检查两种类型的大小,你会看到它们不同(指针)成员更大). (3认同)

Dat*_*yte 5

指向成员函数的指针也需要内存。它们也有尺寸。那么打印出指针的内存怎么样:

template<typename R, typename T, typename... Args>
std::string to_string(R (T::*func)(Args...))
{
    union PtrUnion
    {
        R(T::*f)(Args...);
        std::array<unsigned char, sizeof(func)> buf;
    };
    PtrUnion u;
    u.f = func;

    std::ostringstream os;

    os << std::hex << std::setfill('0');
    for (auto c : u.buf)
        os << std::setw(2) << (unsigned)c;

    return os.str();
}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用它:

class TestClass
{
    void foo();
};

...

std::cout << to_string(&TestClass::foo) << std::endl;
Run Code Online (Sandbox Code Playgroud)