C++ 使用std::function 和std::bin实现委托

来源:互联网 发布:声音提取软件 编辑:程序博客网 时间:2024/06/07 00:04

1.概述
C++11提供的function 和bind函数可以为C++的类之间提供委托,function相当于融合了各种函数,函数指针,lamda表达式还有函数对象等可调用,可回调函数. 抽象出它们共有的属性即只要返回值类型和参数类型一样的可调用对象,不管它是函数,函数指针,还是函数对象都可以被function 统一起来.bind函数返回一个匿名的函数对象,对其sizeof运算发现其占用内存.
2. bind函数不仅可以用于普通的函数,还能用于成员函数,使用函数指针是不能回调成员函数的. 因此将一个函数对象作为一个类的成员变量,再将另外一个类的成员函数bind后复制给该对象,该对象调用这个函数就会去调其他函数的成员函数,实现了委托.

3

class Thread{public:typedef boost::function<void()> ThreadCallback;Thread(ThreadCallback cb): cb_(cb){ }void start(){/* some magic to call run() in new created thread */}private:void run(){cb_();}ThreadCallback cb_;// ...};class Foo // 不需要继承{public:void runInThread();void runInAnotherThread(int)};Foo foo;Thread thread1(boost::bind(&Foo::runInThread, &foo));Thread thread2(boost::bind(&Foo::runInAnotherThread, &foo, 43));thread1.start(); // 在两个线程中分别运行两个成员函数thread2.start();

在类thread中定义了一个函数对象,threadcallbackcb ,实例化thread1 和实例化thread2时将Foo类的成员函数bind后传递给thread的构造函数,因此在thread中调用start的时候会调用run,再调用cb_就调到了Foo类的成员函数.

下面一个例子跟这个类似.

class Connection;class NetServer : boost::noncopyable{public:typedef boost::function<void (Connection*)> ConnectionCallback;typedef boost::function<void (Connection*, const void*, int len)> MessageCallback;NetServer(uint16_t port);~NetServer();void registerConnectionCallback(const ConnectionCallback&);void registerMessageCallback(const MessageCallback&);void sendMessage(Connection*, const void* buf, int len);private:// ...};class EchoService{public:// 符合 NetServer::sendMessage 的原型typedef boost::function<void(Connection*, const void*, int)> SendMessageCallback;EchoService(const SendMessageCallback& sendMsgCb): sendMessageCb_(sendMsgCb) // 保存 boost::function{ }// 符合 NetServer::MessageCallback 的原型void onMessage(Connection* conn, const void* buf, int size){printf("Received Msg from Connection %d: %.*s\n",conn->id(), size, (const char*)buf);sendMessageCb_(conn, buf, size); // echo back}// 符合 NetServer::ConnectionCallback 的原型void onConnection(Connection* conn){printf("Connection from %s:%d is %s\n", conn->ipAddr(), conn->port(),conn->connected() ? "UP" : "DOWN");}private:SendMessageCallback sendMessageCb_;};// 扮演上帝的角色,把各部件拼起来int main(){NetServer server(7);EchoService echo(bind(&NetServer::sendMessage, &server, _1, _2, _3));server.registerMessageCallback(bind(&EchoService::onMessage, &echo, _1, _2, _3));server.registerConnectionCallback(bind(&EchoService::onConnection, &echo, _1));server.run();}

4.结束语
这个功能看起来不是很好理解,但两个类实现了某种意义上的多态,委托给类A则相当于实例化A类,调用A的成员, 把方法委托给类B则相当于实例化B.而且它们的接口必须要一致.

原创粉丝点击