スレッド関数としてのC ++クラスメンバー関数

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()は関数テンプレートに変換されます。したがって、コンパイラはボイラープレートコードのほとんどを自動的に生成します。

おすすめ

転載: blog.csdn.net/weixin_45146520/article/details/109267486