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

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.而且它们的接口必须要一致.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值