2017-11-28 46 views
3

私はしばしば、関数をポインタに基づいて関数が実行されるプロセスに送るコマンドとコントロールのシナリオを扱うときに、関数ポインタを自由に使いました。要求。これは、もはやswitch-case(ジャンプテーブルの最適化を除いて)を使ってそのようなことをする必要がなくなるので、合理的に効率的な実装になります。C++のメンバ関数への関数ポインタの配列の使用

の代わりにこの:

switch(msg.cmd){ 
    case FUNC0: 
     return func0(msg); 

    case FUNC1: 
     return func1(msg); 

    ... 
} 

我々は直接適切なハンドラ(msg.cmdにチェックすべての正気を省略)を実行するために、このような何かを行うことができます。たとえば、最近

(*cmd_functions[msg.cmd])(msg) 

、私が持っています同様の "コントロール"機能を実装しているC++コードで作業を開始しましたが、私はスイッチケースを使用しています。 C++でこれを行う標準的な方法がありますか?おそらく、コンストラクタで初期化された関数ポインタ配列のインスタンス変数ですか?

私は、ソリューションがクラスのVテーブルのランタイム使用のためにもう少し複雑かもしれないと懸念しました。

+0

CのメソッドはC++ではまだ動作しませんか? – JeremyP

+0

私は現代のC++の専門家ではありませんが、今では[lambdas](http://en.cppreference.com/w/cpp/language/lambda)を持っていますので、配列やベクトルなどを作成することはできませんラムダ? – JeremyP

+0

ちょっと不思議なことに、なぜスイッチケースがついていますか?なぜジャンプテーブルが機能しないのですか? – mnistic

答えて

1

デフォルトの解決策は実際にはvテーブルになります。メッセージごとに仮想メソッドを持つ基本クラス/インターフェイスを宣言します。

それぞれの関数を呼び出すにはswitch(msg.cmd) - ステートメントが必要ですが、これは基本的には関数テーブルの初期化を置き換えます。

より洗練された処理が得られ、switch文でもパラメータの変換が行われる可能性があります(メッセージハンドラが「意味のある」引数を得るため)。

テーブルの「構成可能性」が失われます。つまり、関連のないさまざまな具体的なオブジェクトに同じハンドラ関数が割り当てられます。


別の、より一般的なオプションがstd::function<void(MyMsg const &)>で関数ポインタの要素を交換することになる - これは、グローバル/静的関数を割り当てるだけでなく、他のクラスのメンバ関数、ラムダなどだけでなく、できるようになります。署名が一致しない既存の関数に簡単に転送することができます。

ここでの欠点は、テーブルを初期化するコストが高いことです。std ::関数を構築するには、少なくとも一般的な場合にはおそらく割り当てが必要です。また、典型的なvテーブル固有の最適化を逃してしまうので、少なくとも当面はより高いコストで通話が期待されます。この時点で


、あなたはまた、異なるアーキテクチャを検討する必要があります少なくとも、各メッセージに複数の「リスナー」がある場合のために、あなたは、イベントサブスクリプションまたはシグナル/スロットの設計を検討する必要があります。


もちろん、あなたはCのやり方に固執することもできます。いいです。

関連する問題