2016-12-07 6 views
0

オブジェクトをに渡して、キューを持つスレッド間で値を渡そうとしています。スレッド間でオブジェクトを値渡しします

複数の異なるオブジェクトが存在するため、抽象クラスを作成しました。

class message 
{ 
public : 
     virtual ~message(){}; 
}; 

その後、私は、メッセージ

class a_specific_message : public message 
{ 
... 
}; 

のそれぞれ異なるタイプのサブクラスを持っている私は、キューを実装するためのthis tutorialを読んで、私は次のようにそれを呼び出す:

concurrent_queue<message> queue; 
a_specific_message m{1, 2, 3}; 
queue.push(m); 

私の問題がありますキューがメッセージをクローンできるようにoperator=を上書きする必要があることを確認してください。

popped_value=the_queue.front(); 

仮想演算子を追加しようとしましたが、サブクラスで呼び出されません。

オブジェクトを参照渡しすることなく、このようなことをどのように達成できるかわかりません。

+1

'concurrent_queue 'は 'message'型の**オブジェクト**を保持します。派生型のオブジェクトをキューにプッシュすると、オブジェクトはスライスされ、格納されているものはすべてその 'message'部分です。元のオブジェクトを元に戻す方法はありません。参照またはポインタを保持するキューが必要です。 –

+0

@PeteBecker私はこれが起こることを恐れていました。他のスレッドがオブジェクトを削除したことを確認するにはどうすればいいですか? – Marc

+2

'shared_ptr'(スレッドセーフです)のような音です。 – Donnie

答えて

2

私の意見では、多型はあなたが本当に望むものではありません。デストラクタとダイナミックダウンキャスト以外のインタフェースは通常、間違ったツールを使用していることを意味します。多型は、あなたが望むものである場合


しかし、私はstd::unique_ptrを提案してみましょう。あなたはあなたにここでそのように宣言ポインタのキューを持つことができます。concurrent_queue<std::unique_ptr<message>>

あなたはコメントで語ったとおり:私は開発者が別のスレッドでそれを削除することを忘れないようにしなければならないので、ポインタを使用したくありませんでした

。忘れてしまい、メモリリークが発生する可能性があります。

次に、私はstd::unqiue_ptrがあなたにとって正しいことだと思います。値をポップする

concurrent_queue<std::unique_ptr<message>> queue; 

queue.push(std::make_unique<a_specific_message>(1, 2, 3)); 
// Or 
queue.push(new a_specific_message{1, 2, 3}); 

次に、::

私はあなたのコードを変換する場合、それはそのようになります。

concurrent_queue<std::unique_ptr<message>> queue; 
auto m = std::make_unique<a_specific_message>(1, 2, 3); 

queue.push(std::move(m)); 

それとも単にを

auto popped_value = std::move(the_queue.front()); 

はその後すべてが削除されますポインタを削除することを忘れずに自動的に実行されます。その目的のためにstd::unique_ptrが作成されました。

あなたのコード内で明示的な動きを避けるために、あなたはあなたのキューにpop_valueのようなものを持っている可能性があり、そのように実装:

T pop_value() { 
    auto value = std::move(the_queue.front()); 

    the_queue.pop(); 

    // use nrvo 
    return value; 
} 

だから今、あなたのスレッドで、あなたが安全にそれを行うことができます

{ 
    auto some_message = queue.pop_value(); 

    // stuff 

} // some_message deleted here. 
+0

make_uniqueはC++ 14ですか?私はそれがstdのメンバーではなく、私はC++を使用しているというエラーを受け取ります。 – Marc

+1

はい、 'std :: make_unique'はC++ 14の一部です。しかし 'std :: make_unique'を普通の古い' new'で置き換えることができます –

+0

@Marcは私の編集を参照してください。 'std :: unique_ptr'と互換性のある新しい例を追加しました –

2

@PeteBeckerがコメントに書いている通り、concurrent_queue<message>は値でmessageを保持します。派生オブジェクトインスタンスがキューにプッシュされると、messageのコピーのみが作成されます。スライスが発生します。

ポインタに頼らずにキューに複数の型のオブジェクトを保持させる1つの方法は、識別された共用体を使用することです。 boost::variant

using message = boost::variant<specific_message_a, specific_message_b>; 

メッセージの共通基本クラスはここでは必要ありません。

このアプローチの欠点は、そのboost::variant<>テンプレート引数リストの中で最大タイプのsizeof(message)sizeofであることです。

関連する問題