オブジェクト指向では、通常、インターフェイスを使用してコールバックを実装します: (大まかな例)
class Message {}
class IMsgProcessor {
public:
virtual void handle_msg(const Message& msg) = 0;
}
class RequestMsgProcessor : public IMsgProcessor {
virtual void handle_msg(const Message& msg) {
// process request message
}
}
class CustomSocket {
public:
Socket(IMsgProcessor* p) : processor_(p) {}
void receive_message_from_network(const Message& msg) {
// processor_ does implement handle_msg. Otherwise a compile time error.
// So we've got a safe design.
processor_->handle_msg(msg);
}
private:
IMsgProcessor* processor_;
}
ここまでは順調ですね。C++11 では、これを行う別の方法として、CustomSocket に std::function オブジェクトのインスタンスを受け取るだけにする方法があります。実装されている場所や、オブジェクトが null 以外の値であるかどうかは気にしません。
class CustomSocket {
public:
Socket(std::function<void(const Message&)>&& f) : func_(std:forward(f)) {}
void receive_message_from_network(const Message& msg) {
// unfortunately we have to do this check for every msg.
// or maybe not ...
if(func_)
func_(msg);
}
private:
std::function<void(const Message&)> func_;
}
1. パフォーマンスへの影響はどうですか? 仮想関数呼び出しは関数オブジェクトを呼び出すよりも速いと思いますが、どれくらい速いですか? 私は高速メッセージング システムを実装していますが、不必要なパフォーマンスの低下は避けたいと考えています。
2. ソフトウェア エンジニアリングの実践に関しては、私は 2 番目のアプローチの方が好きだと言わざるを得ません。より少ないコード、より少ないファイル、より少ない混乱: インターフェイス クラスはありません。柔軟性の向上: 一部の関数オブジェクトを設定し、他のオブジェクトを null のままにすることで、インターフェイスのサブセットのみを実装できます。または、(単一のサブクラスではなく) 個別のクラス、フリー関数、または両方の組み合わせによって、インターフェイスのさまざまな部分を実装することができます。さらに、CustomSocket は、IMsgProcessor のサブクラスだけでなく、任意のクラスで使用できます。これは私の意見では、大きな利点です。
あなたは何を言っていますか?これらの議論に何か根本的な欠陥があると思いますか?