C语言中的注册回调函数到了C++中有了更好的实现方式,这就是boost::function和boost::bind,bind为普通函数、成员函数提供参数绑定,把他们变成函数对象,而function则可用于保存由bind生成的函数对象。这样就由C中保存函数指针的形式变成C++中保存函数对象的形式,这样对于用户来说不管是传递函数指针或者函数对象都能正确的执行程序,摆脱了C中只能用函数指针的限制。
下面举Beyond the C++ Standard Library: An Introduction to Boost中的一个例子,这个例子实现了把业务逻辑从表示层分离开来。
Tape.h
#ifndef TAPE_H
#define TAPE_H
class Tape{
public:
void play();
void stop();
void record();
};
#endif
Tape.cpp
#include "Tape.h"
#include <iostream>
using namespace std;
void Tape::play(){
cout<<"play tape\n";
}
void Tape::stop(){
cout<<"stop tape\n";
}
void Tape::record(){
cout<<"record tape\n";
}
这是一个录音机类,实现了简单的开关和记录功能,这是类的实现部分,现实应用中我们就需要对录音机发号各种命令,也就是说我们需要各种Command类来操作录音机,而为了录音机的实现和控制部分解藕,则可以使用4人帮介绍的Command模式,这样我们就需要定义一个Command的抽象基类,和一系列派生类,PlayCommand,StopCommand,RecordCommand,也就是说由多小命令就定义多少种派生类。PlayCommand类如下所示:
class PlayCommand:public Command{
Tape *p_;
public:
PlayCommand(Tape * p):p_(p){}
bool enabled()cosnt{
return true;
}
void execute(){
p_play();
}
};
测试代码
int main(){
Tape tape;
Command *pPlay = new PlayCommand(&tape);
Command *pStop = new StopCommand(&tape);
pPlay->execute();
pStop->execute();
delete pPlay;
delete pStop;
}
StopCommadn和RecordCommand实现和PlayCommand只有execute()不同,即分别调用stop(),record(),你会发现3个类都一样,调用的函数参数类型和返回类型都一样,那么就可以把这3个函数再抽象一下,用泛型的形式来表示,这样就是Function的形式了。有了Function这样我们再不用Command及其的派生类了,我们只需要定义一个
typedef boost::function<void ()> Command;
3个函数被抽象成没有返回值,没有参数的Function了。测试函数如下所示:
#include "Tape.h"
//#include "Command.h"
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace boost;
typedef function<void ()> Command;
int main(){
Tape tape;
Command play( bind(&Tape::play,&tape ));
Command stop( bind(&Tape::stop,&tape ));
play();
stop();
Command record( bind(&Tape::record,&tape) );
record();
}
也就是说Command的一系列类被一句typedef的功能完全替代了,大大减少了代码量。