C ++クラスメンバー関数が使用される場合、thisポインターは暗黙的に関数に渡され、thisポインターはクラスのオブジェクトを指します。関数本体は、ポインターを明示的に呼び出すことも、クラスのメンバーに直接アクセスすることもできます。
コールバック関数は、ポインターによって呼び出される関数です。最も一般的に使用されるコールバック関数は、関数ポインターと、スレッドの作成時に関数に渡される複数のパラメーターを使用してスレッド関数を呼び出すことにより、スレッドを作成することです。ライブラリ関数がコールバック関数を使用すると、コールバック関数宣言に準拠する指定されたパラメーターがコールバック関数に渡され、クラスメンバー関数に暗黙的に含まれるため、一般クラスメンバー関数をコールバック関数として使用することはできません。このポインタパラメータ。したがって、クラスメンバー関数をコールバック関数として使用すると、パラメータが一致しない場合にエラーが発生します。std :: threadの場合、最初のパラメーターは関数ポインターです。C++では、この方法ではメンバー関数のポインターを取得できないため、エラーが報告されます。
解決策1:
メンバー関数を静的メンバー関数として設定します。静的メンバー関数はオブジェクトに属していませんが、このポインターなしでクラス全体に属しています。ただし、静的メンバー関数は非静的メンバー変数を使用できず(特定のオブジェクトのthisポインターがないため)、オブジェクトまたはクラスポインターを介して呼び出すことができます。
解決策2:
このポインターなしでメンバー関数をフレンド関数として宣言しますが、クラスのメンバー変数にはアクセスできます。
解決策3:
別のスレッドでHackクラスの非静的メンバー関数func2()を呼び出す必要があるとします。メンバー関数のアドレスをthr_create()に直接渡す必要はなく、void *パラメーターを使用して通常の関数を宣言します。
intermediary(void *)、そしてそれを呼び出します:
void intermediary(void);
次に、構造を作成します。構造は次のように定義されます。
struct A
{
Hack * p; //类对象指针
void (Hack::*pmf)(); // 成员函数指针
};
構造体インスタンスを作成し、構造体に目的のオブジェクトアドレスとメンバー関数アドレスを入力します。
A a; // 结构实例
Hack h; // 创建对象
//填充结构
a.p = & h;
a.pmf = &Hack::func2; // 取成员函数地址
ここで戻って、intermediate()関数を実装します。
void *intermediary(void* ptr)
{
A* pa=static_cast < A* > (ptr); // 强制转换 p 为 A*
Hack* ph=pa->p; // 从A中析取Hack对象地址
void (Hack::*pmf)()=pa->pmf; // 析取 ptr 到成员函数
(ph->*pmf)(); // 调用成员函数
}
最後に、intermediate()のアドレスをthr_create()に渡します。
pthread_create(&ptid、NULL、中間、(void *)&a);
pthread_create()は関数intermediate()を呼び出し、Aのアドレスをそれに渡します。次に、intermediary()は、ポインターパラメーターから構造体Aを展開し、目的のメンバー関数を呼び出します。この間接的な方法
スレッドライブラリがメンバー関数をサポートしていない場合でも、処理は別のスレッドでメンバー関数を安全に開始できます。異なるクラスの異なるメンバー関数を呼び出す必要がある場合は、構造体Aをクラステンプレートに変換し、関数を変更できます。
intermediary()は関数テンプレートに変換されます。したがって、コンパイラはボイラープレートコードのほとんどを自動的に生成します。