16

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::coutですか?

4

4 に答える 4

19

これを行うための機能が言語によって提供されているとは思いません。operator <<ストリームが通常のポインターを出力するためのオーバーロードがありますvoid*が、メンバー関数ポインターはvoid*s に変換できません。これはすべて実装固有ですが、通常、メンバー関数ポインターは値のペア (メンバー関数が仮想かどうかを示すフラグと追加データ) として実装されます。関数が非仮想関数である場合、その追加情報は通常、実際のメンバー関数のアドレスです。関数が仮想関数である場合、その追加情報には、仮想関数テーブルにインデックスを付けて、指定された受信側オブジェクトを呼び出す関数を見つける方法に関するデータが含まれている可能性があります。

一般に、これは、未定義の動作を呼び出さずにメンバー関数のアドレスを出力することは不可能であることを意味すると思います。この効果を得るには、おそらくコンパイラ固有のトリックを使用する必要があります。

お役に立てれば!

于 2012-06-20T02:18:57.253 に答える
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)')))))
于 2012-06-20T03:25:58.867 に答える
6

それを行う1つの方法は次のとおりです(移植可能かどうかはわかりません):

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

作業例: http://ideone.com/1SmjW

于 2012-06-20T02:30:42.640 に答える