純粋仮想メソッドVS.関数ポインタ
-
20-08-2019 - |
質問
最近私はThreadクラスライブラリを設計してきた、私が作った次のようなスレッド抽象クラスます:
class Thread {
public:
run() { /*start the thread*/ }
kill() { /*stop the thread*/ }
protected:
virtual int doOperation(unsigned int, void *) = 0;
};
リアルタイムスレッドクラスは、この抽象クラスを継承し、独自のロジックでdoOperation
メソッドを実装し、戦略のようなものでしょうパターンでます。
問題は、私は次の関数でスレッドを実行している定義Cバックエンドライブラリに頼ってるということです。
int startThread(char* name, (int)(*)(unsigned int, void*), int, int, int, void*);
あなたが見ることができるように。第2のパラメータは、スレッドのループへの関数ポインタ(メイン関数)であり、ここでは問題です。私はrun
方法でスレッドを開始するには、このC-関数を使用するので、私は2番目のパラメータにdoOperation
のアドレスを渡し、そしてこれは、型の不一致により、行うことができない。
私はポインタを返すためにreinterpret_cast
を使用しようとしましたが、私ISO-C ++は、初期化されていない関数メンバーのポインタを返す禁止します。
私は、静的メソッドを使用すると、私は推測する唯一のソリューションである、この対立を克服する方法がわからないが、それは私の設計パターンを吹く!
解決
まず、それは良い情報が含まれているとして、マイケル・バリが提供されるリンクを必ずお読みください。そこで、ここではそのためのC ++っぽい擬似コードがあります:
int wrapperDoOperation(int v, void *ctx)
{
Thread *thread = (Thread *)ctx;
return thread->doOperation(v);
}
class Thread {
public:
run() {
startThread("bla", wrapperDoOperation, bla, bla, bla, (void *)this);
}
kill() { /*stop the thread*/ }
protected:
virtual int doOperation(unsigned int) = 0;
friend wrapperDoOperation ......;
};
アイデアはdoOperationは、スレッドのメンバ関数であること、ボイド*コンテキストを必要としないということです、あなたはちょうどあなたがオブジェクト自体のコンテキストとして渡すものは何でも続けることができます。そのため、あなたはdoOperationにactuallにこのポインタを渡すためにボイドポインタを使用することができます。無効*詳細はいいですが、あなたのクラスのユーザーから隠されていることに注意してください。