在 OO 中,通常使用接口实现回调:(粗略示例)
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 对象的实例。它不关心它是在哪里实现的,也不关心对象是否为非空值:
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. 在软件工程实践方面,我不得不说我更喜欢第二种方法。更少的代码,更少的文件,更少的混乱:没有接口类。更大的灵活性:您只能通过设置一些函数对象而将其他函数对象保留为空来实现接口的子集。或者,您可以在单独的类中或通过自由函数或两者的组合(而不是在单个子类中)实现接口的不同部分。此外,任何类都可以使用 CustomSocket,而不仅仅是 IMsgProcessor 的子类。这是一个很大的优势,在我看来。
你说什么?你认为这些论点有什么根本缺陷吗?