3

C++の関数ポインタに関して、クラス関数とグローバル関数の違いは何ですか? 関数がクラスメンバーである場合、WindowsのCreateThreadメソッドはスレッドコードが入る関数を受け入れないように見えるので、私は尋ねています。

グローバルメソッドの場合、(スレッドコードが入る) 関数を CreateThread メッセージに渡すことができますが、クラスのメンバーにすると、「タイプ [メソッドレイアウト] の引数はパラメーターと互換性がありません」というエラーが表示されます。タイプLPTHREAD_START_ROUTINEの」。ClassName::* は現在中間にあります。これは影響していますか?

これを回避する方法は何ですか?

4

2 に答える 2

5

メンバー関数ポインター ( DWORD(WINAPI Foo::*)(LPVOID)) は、関数ポインター ( ) とは異なる型ですDWORD(WINAPI *)(LPVOID)。メンバー関数には隠しthisパラメーターがあり、署名の不一致が発生します。

これを行う最も簡単な方法は、C++11 の<thread>ヘッダーを使用することです。

struct Foo {
    void threadProc() {}
};

int main() {
    Foo foo;
    std::thread t{&Foo::threadProc, foo, /*other arguments to threadProc*/};
    t.join();
}

に頼る必要がある場合CreateThreadは、void *パラメーターを使用してインスタンスを渡します。

struct Foo {
    DWORD threadProc() {...}
};

extern "C" DWORD WINAPI proxyThreadProc(LPVOID userData) {
    auto foo = static_cast<Foo *>(userData);
    if (foo) {foo->threadProc();}
}

int main() {
    Foo foo;
    CreateThread(..., proxyThreadProc, &foo, ...);
}

std::functionクラス内のものは、プロキシ プロシージャ内から適切な引数を使用して呼び出される限り、( のように) ほとんど何でも好きなものにすることができ、引き続き機能します。

于 2013-08-14T11:05:03.067 に答える
0

ええ、@chrisが言ったように、これにはパラメーターの最後で接続される隠しポインターがあります。スレッドがそれを実行すると、最後のパラメーターの位置にあるポインターとの一致がわからず、終了時にこの関数のヒープを回復できなかったため、クラスの非静的メンバー関数を使用することは禁止されていますクラスのグローバル関数または静的メンバー関数を除くスレッド関数を駆動します。

于 2013-08-14T12:32:35.183 に答える