別のスレッドで実行オブジェクトのメンバー関数

質問をします

事実上、すべてのスレッドがないC ++クラスのメンバ関数、C関数を処理するために使用されています。標準ライブラリは、コールバック関数のポインタがスレッドとしてコードを実行することがAPI関数を提供し、別のスレッドでコールバック関数を呼び出します。問題は、このようなスレッドライブラリでのスレッドの実行オブジェクトのメンバ関数を作成することはできませんです。唯一の定期的な機能。したがって、次のコードは失敗です。

//スレッドスレッドライブラリ関数起動
int型のthr_create(無効(PF *)()、void *型PRM、thread_tの* PTHを); 

の#include "class1.h" 

のint FUNC(ボイド*ののparam)
{ 
T1 thread_tの; 
//次の呼び出しコンパイラエラーを引き起こす: "の')(無効(クラス1 :: *) ''のために変換することはできません' ''無効(*)() 'から'" 
//のタイプに変換することはできません意味
リターンのthr_create(&class1に:: some_method、 PARAMを、 T1&); 
}

()コールバック関数のアドレスニーズ、void *型のポインタをパラメータと同様に、可変thread_tのののthr_createの機能を渡し、コールバック関数のアドレスへの引数として渡されます。

最初のパラメータは、のthr_create()メンバ関数に渡されたので、上記のコードのコンパイルが失敗した理由は、代わりに、通常の関数ポインタ、クラス1のポインタです。概念的には、一般的な機能とクラスのメンバ関数は、2つの完全に異なるものです。でも、キャストが動作しない場合。それでは、どのようにこの問題を解決するには?

ソリューション

静的メンバ関数を使用します

最初のソリューションは、静的メンバ関数コールバックを作ることです。暗黙のパラメータ「この」なしの静的メンバ関数ので。これにより、アドレスポインタのパラメータは、通常の機能を使用するとみなすことができます。静的メンバ関数のデータメンバからオブジェクトへのアクセスは、明示的に入ってくるオブジェクトに対処している場合。例えば:

ハッククラス
{ 
プライベート:
int型X; 
公共:
int型get_x(); 
静的ボイドFUNC(ハック* pThis); //静的メンバ関数
のボイド関数func2(); //非静的メンバ関数
}; 

無効ハック:: FUNC(ハック* pThis)
{ 
int型Y = pthis-> get_x(); //アクセス対象データメンバ
}

この方法は、ほとんどの場合、実行可能であることができ、時には静的メンバ関数として宣言することはできません、その関数は仮想メンバ関数であるか、変更することはできません、サードパーティのクラスを使用しています。これが発生した場合、問題を解決する方法がより困難です。

非静的メンバ関数の処理

非静的メンバ関数func2のハッククラスが別のスレッドで呼び出す必要があると仮定すると()。直接、)(thr_createに転送メンバ関数を扱う通常の関数仲介(ボイド*)の文を使用して、void *型の引数、およびそれを呼び出すことはありません。

空仲介(ボイド*);

次に、以下のような構造が定義され、構造を作成します。

構造体
{ 
ハック* P; //クラスオブジェクトへのポインタ
ボイド(ハック:: * PMF)( ); // メンバ関数ポインタ
}。

構造体のインスタンスを作成し、構造は、所望の目標アドレスとメンバ関数のアドレスが充填されています。

A; //構成例
Hをハック; //オブジェクトを作成
//充填構造
AP =&H; 
ハックa.pmf :: =&関数func2; //メンバ関数のアドレスを取得します

今すぐ戻って仲介()関数を実装します。

中間空隙(ボイド* PTR)
{ 
* PA = static_castを<A *>(PTR); // pは、鋳造される* 
ハック液pH = * PA-> P; //ハックは、対象アドレスから抽出された
空隙(ハック:: * PMF)()= PA-> PMF; // メンバ関数はPTR抽出する
(PH - > * PMF)を( ); // メンバ関数呼び出し
}

最後に、仲介者は、()()のthr_createに対処するために渡されます。

thr_create(仲介、(ボイド*)&、&T1)。

thr_create()関数は、仲介()を呼び出し、アドレスAは、それに渡されます。仲介者()とその構造ポインタパラメータAと所望のメンバ関数呼び出しを展開。この治療の間接的な方法は、安全にさえスレッドライブラリは、メンバ関数をサポートしていない、別のスレッドでメンバ関数を起動することができます。あなたは異なるクラスの異なるメンバーの関数を呼び出す必要がある場合は、構造体は、テンプレートがテンプレートを変換するために、仲介()関数を機能するクラスに変換することができます。だから、コンパイラが自動的に定型コードの大部分を生成します。

ます。https://www.cnblogs.com/rogee/archive/2011/03/31/2000495.htmlで再現

おすすめ

転載: blog.csdn.net/weixin_34217773/article/details/94680667