2

最近、私は Thread クラス ライブラリを設計しており、次のような Thread 抽象クラスを作成しました。

class Thread {
public:
    run() { /*start the thread*/ }
    kill() { /*stop the thread*/ }
protected:
    virtual int doOperation(unsigned int, void *) = 0;
};

実際のスレッド クラスは、この抽象クラスを継承doOperationし、独自のロジックでメソッドを実装します。これはStrategy Patternに似ています。

問題は、次の関数でスレッドの実行を定義する C バックエンド ライブラリに依存していることです。

int startThread(char* name, (int)(*)(unsigned int, void*), int, int, int, void*);

ご覧のように; 2 番目のパラメーターは、スレッドのループ (メイン関数) への関数ポインターであり、ここに問題があります。この C 関数を使用してrunメソッド内のスレッドを開始するため、アドレスをdoOperation2 番目のパラメーターに渡しますが、型が一致しないため、これを行うことができません。

ポインターを返すために使用しようとしましたreinterpret_castが、ISO-C++ は、初期化されていない関数メンバーのポインターを返すことを禁止しています。この競合を克服する方法がわかりません。静的メソッドを使用することが唯一の解決策だと思いますが、それは私の設計パターンを爆破します!

4

1 に答える 1

7

最初に、Michael Burr が提供したリンクをよく読んでください。適切な情報が含まれています。次に、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 ......;
};

Thread のメンバー関数である doOperation は void *context を必要とせず、オブジェクト自体にコンテキストとして渡すものは何でも保持できるという考え方です。したがって、void ポインターを使用して、実際の this ポインターを doOperation に渡すことができます。void * の詳細がクラスのユーザーから隠されていることに注意してください。これは素晴らしいことです。

于 2009-02-01T09:35:26.940 に答える