1

基本クラスのメソッドをスレッドとして開始する子クラスがあります。子クラスは、基本クラスからの純粋仮想メソッドも実装しています。次に、スレッドは、スレッド内の純粋仮想メソッドの子の実装バージョンを呼び出す必要がありますが、スレッドは「純粋仮想メソッドが呼び出されました」という例外をスローします。以下のコードは、Child の構築時に何が起こるかを示しています。

class Base {
  std::thread messageThread;

  virtual void processMessage(std::string msg) = 0;

  static void checkForMessages(Base *c) {
    while(true) {
      std::string msg = "Hello";
      c->processMessage(msg);
    }
  }
};

class Child : public Base {
  Child() {
    messageThread = std::thread(checkForMessages, this);
  }

  void processMessage(std::string msg) {
     std::cout << "Message: " << msg << std::endl;
  }
};

私の理解では、コンストラクターが終了するまで Child は引き続き Base と見なされるため、スレッドは processMessage を純粋な仮想関数としてしか見ることができません。Base のすべての子に対して checkForMessages を実装することもできますが、それではそもそも Base クラスを持つという目的が無効になります。

これを正しく実装するにはどうすればよいですか? お手伝いありがとう!

編集: 問題を示す完全な例と、修正を試みた例: https://gist.github.com/4590476

4

3 に答える 3

3

オブジェクトが構築された後に呼び出し元によって呼び出される必要がstd::thread(checkForMessages, this)ある別のメソッドに移動できます。start()

于 2013-01-21T22:42:37.113 に答える
1

Derivedスレッドが実行される前に のインスタンスが破棄される (または少なくとも開始される) ことを止めるものは何もありません。いくつかのスマート ポインターまたは同期が必要です。

于 2013-01-21T23:30:28.450 に答える
1

これを解決する方法は明らかにたくさんあります。私の提案は、スレッドをラップするクラスと「チェックメッセージ」を実装するクラスの 2 つのクラスを使用することです。

lass Base {
  std::thread messageThread;

  virtual void processMessage(std::string msg) = 0;

  static void checkForMessages(Base *c) {
    while(true) {
      std::string msg = "Hello";
      c->processMessage(msg);
    }
  }
};

class Child : public Base {
  Child() {
  }

  void processMessage(std::string msg) {
     std::cout << "Message: " << msg << std::endl;
  }
};

class ThreadWrapper
{
    ThreadWrapper(Base *b)
    {
        messageThread = std::thread(Base::checkForMessages, this);
    }
    ... 
}

....
Child child;
ThreadWrapper tw(&child);

もう 1 つの明らかな選択肢は、別のメンバー関数でスレッドを開始することです。

どちらも「良い」ものではない場合は、その理由を説明してください。おそらく、他のアイデアを思い付くことができます。

「別の関数からスレッドを開始する方法」のいくつかのスニペットを次に示します。

class Child: public Base public: Child() { }

    void start(void) { messageThread = std::thread(checkForMessages, this); }


    ~Child() {
        messageThread.join();
    }

....

int main()
{
    Child c;
    c.start();

また、しばらくすると終了するように checkForMessage を変更しました。私のテストケースで動作します。

于 2013-01-21T22:46:02.927 に答える