メンバ関数の呼び出し規約
なんとなくC++のメンバ関数の呼び出し規約を調べてみたという件。
VC++2005以降では__thiscallという名前がついていることを知った。
で、もしかして__cdeclつけたら、_beginthread()の引数にもできるのか?と思ったらできた。(VC6/2005で確認)
#include <Windows.h> #include <Process.h> #include <iostream> struct A { void __cdecl Self(void) { std::cout << "this: " << this << std::endl; } }; int main(int argc, char *argv[]) { A a; a.Self(); // 普通に呼び出し void (__cdecl A::*Self)(void) = &A::Self; // 直接キャストできないので変数にコピーしておく _beginthread((void (*)(void *))*(void **)&Self, 0, &a); // 引数としてthisを渡す Sleep(1000); return 0; }
この方法だとthisが(ecxではなく)スタックに積まれる。staticメンバ関数を介さずに呼び出すことができるので、staticメンバ関数の名前について悩んだり議論したりする手間が省ける。
thisをvoid *にキャストしているのでthisポインタのサイズがvoid *と異なる場合には問題だが、それはstaticメンバ関数を使う場合でも同じではある。