代码之家  ›  专栏  ›  技术社区  ›  Amir

如何打印非静态方法地址?[复制品]

  •  0
  • Amir  · 技术社区  · 7 年前

    看起来像 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;
    }
    

    结果是这样的:

    003111DB
    1
    

    如何打印 MyFunc 的地址使用 STD:: ?

    0 回复  |  直到 11 年前
        1
  •  16
  •   templatetypedef    14 年前

    我不相信有任何语言提供的设施来做这件事。存在的重载 operator << 供流正常打印 void* 指针,但成员函数指针不能转换为 空洞* 这都是特定于实现的,但通常成员函数指针是作为一对值实现的——一个标志,指示成员函数是否是虚拟的,以及一些额外的数据。如果函数是非虚函数,则该额外信息通常是实际成员函数的地址。如果函数是一个虚拟函数,那么额外的信息可能包含有关如何索引到虚拟函数表中以找到给定接收方对象要调用的函数的数据。

    一般来说,我认为这意味着不调用未定义的行为就不可能打印出成员函数的地址。您可能需要使用一些特定于编译器的技巧来实现这种效果。

    希望这有帮助!

        2
  •  13
  •   Panayiotis Karabassis    14 年前

    我想补充一下其他的答案,您打印“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)')))))
    
        3
  •  5
  •   Mr.Anubis    14 年前

    一种方法是(我不确定它是否便携):

    void TestClass::PrintMyFuncAddress(void)
    {
      void (TestClass::* ptrtofn)() = &TestClass::MyFunc;
      cout << (void*&)ptrtofn<< endl;
    }
    

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

        4
  •  2
  •   Databyte    11 年前

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

    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();
    }
    

    你可以这样使用它:

    class TestClass
    {
        void foo();
    };
    
    ...
    
    std::cout << to_string(&TestClass::foo) << std::endl;
    
    推荐文章