使用接口或函数对象回调? [英] Callback with interfaces or function objects?

查看:134
本文介绍了使用接口或函数对象回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在OO中,通常使用接口实现回调:(粗略的例子)

In OO, one usually implements callbacks with interfaces: (rough example)

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对象的实例。它不关心它在哪里实现,即使
对象是非空值:

So far so good. With C++11, another way to do this is to have CustomSocket just receive an instance of std::function object. It does not care where it is implemented or even if the object is a non-null value :

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.在软件工程实践方面,我不得不说我更喜欢第二种方法。少代码,少文件,更少杂乱:没有接口类。更多的灵活性:您只能通过设置一些函数对象并将其余的为null来实现接口的一个子集。或者你可以在不同的类中实现接口的不同部分,或者通过自由函数或两者的组合(而不是在单个子类中)。此外,CustomSocket可以被任何类使用,而不仅仅是IMsgProcessor的子类。这是一个很大的优势,在我看来。

你说什么?

Now here are the questions:
1. What about the performance impacts? I'm guessing a virtual function call is faster than calling a function object but how much faster? I'm implementing a fast messaging system and I'd rather avoid any unnecessary performance penalty.
2. In terms of software engineering practices, I have to say I like the second approach better. Less code, fewer files, less clutter: no interface class. More flexibility: you can only implement a subset of the interface by setting some of the function objects and leaving the others null. Or you can have different parts of the interface implemented in separate classes or by free functions or combination of both (instead of in a single subclass). Furthermore, CustomSocket can be used by any class not just subclasses of IMsgProcessor. This is a great advantage, in my opinion.
What do you say? Do you see any fundamental flaw in these argument ?

推荐答案

您可以充分利用这两个世界

You can have the best of both worlds

template<class F>
class MsgProcessorT:public IMsgProcessor{
  F f_;
  public:
  MsgProcessorT(F f):f_(f){}
  virtual void handle_msg(const Message& msg)  {
      f_(msg);
 }

};
template<class F>
IMsgProcessor* CreateMessageProcessor(F f){
    return new MsgProcessor<T>(f);

};

然后您可以像这样使用

Socket s(CreateMessageProcessor([](const Message& msg){...}));

或者更容易向Socket添加另一个构造函数

Or to make it even easier add another constructor to Socket

class Socket{
...
template<class F>
Socket(F f):processor_(CreateMessageProcessor(f){}


};

然后你可以做

Socket s([](const Message& msg){...});

仍然具有与虚函数调用相同的效率

And still have the same efficiency as a virtual function call

这篇关于使用接口或函数对象回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆