2017-07-30 27 views
0

以下に示すように、基本クラスメソッド内からスレッドを生成するときは、純粋仮想メソッド実装を呼び出す必要があります。スレッド内で純粋仮想メソッドを呼び出す

#include <iostream> 

class Foo { 
    private: 
    std::thread tr; 

    public: 
    virtual void baz() = 0; 
    void foo() { 
     this->tr = std::thread([=] { this->baz(); }); 
    } 

}; 

class Bar : public Foo { 
    public: 
    void baz() { 
     std::cout << "In baz" << "\n"; 
    } 

}; 

メインクラス...

#include <thread> 
#include "test.hpp" 

int main(int argc, char* argv[]) { 
    Bar b; 
    b.foo(); 
} 

しかし、それはメッセージ

呼ば

純粋仮想メソッドアクティブな例外なしで呼び出さ

終了で失敗します10

「純仮想メソッドが呼び出されました」というメッセージは、一部のエラーメッセージにのみ表示されます。私は間違って何をしていますか?それはバーや不適切に破壊されてスレッドに関連して何か?

+2

スレッドにはどこに参加していますか?あなたのメインがすぐに完了するのを止めるのは何ですか? – xaxxon

+4

あなたのプログラムは、ワーカースレッドの 'baz()'呼び出しとメインスレッドの '〜Bar()'呼び出しの間で、 'b'のデータ競争によって未定義の動作を示します。スレッドが 'this-> baz()'に到達する前に 'main'が返って' b'が破棄される可能性が最も高いでしょう。 –

+0

純粋仮想メソッドを呼び出す必要はありません。これは要件ではなく、*問題です。 – EJP

答えて

2

Igorが彼のコメントで指摘したように、あなたはデータ競争があります。スレッドは実際にはBarが破壊された後に実行されます(実際の実行順序は定義されていませんので、場合によっては幸運になるかもしれません)。これを防ぐには、に、Barが破壊される前にする必要があります。あなたはこれ以上調査したい場合は

class Foo { 
    std::thread tr; 
protected: 
    void join() { tr.join(); } 
public: 
    virtual ~Foo() = default; // ~Foo should be virtual or protected, if Foo contains virtual methods 
    virtual void baz() = 0; 
    void foo() { 
     this->tr = std::thread([=] { this->baz(); }); 
    } 
}; 

class Bar : public Foo { 
public: 
    ~Bar() { join(); } 
    void baz() { std::cout << "In baz" << "\n"; } 
}; 

は、様々な方法でいくつかのcout S(特にデストラクタ)を追加し、さまざまな場所でstd::this_thread::sleep_for (std::chrono::seconds(1))を追加します。

+3

'join'は'〜Foo'ではなく '〜Bar'で呼び出されるべきであることに注意してください。 OPデザインが壊れやすくなります。 – Jarod42

+1

@ Jarod42私は同意する、このデザインは壊れやすいです。 '〜Foo'で手動で結合することは何もしません。これはスレッドが破壊されたときに起こります(しかし、'〜Bar'が破壊された後に起こります)。しかし、私はOPデザインであまり詳しく説明したくなかった... – chtz

+0

@chtz何か条件付きで使うのですか?これは、スレッドが実行を終了する前にオブジェクトを破棄したり、スレッドが無効なメモリをアドレス指定したりすることを許さないようにする必要があります(純粋な呼び出しは実装固有のようです)。いずれにしてもMicrosoftコンパイラの問題ではないようですが、この問題はLinux上のQtQuickオブジェクト(別のスレッドでJscriptを実行するため)で発生しますが、Windowsでは発生しません。 – Swift

関連する問題