表驱动:
1种用于代替多层if-else/ switch case的一种处理方式
根据不同的输入(msgType),进行不同的处理(函数指针)或赋值
在c语言中表驱动格式往往是:
struct {
MsgType msgType;
FuncPtr funcPtr;
} Select handle[] = {
{....}, {....}, {....}, {....}, {....},
};
if (...) {
// 根据类型选择相应的函数/处理
handle[msgType->Idx].funcPtr(...);
}
对于表长度不算长,且消息类型的值不大的场景,甚至可以将消息类型的值作为索引,代替遍历
c++中的表驱动:
1.非静态成员函数,静态表
如果针对不同消息类型函数的处理放在了类中,按以前c的写法是不行的,要换一下
class FuncTbl {
public:
void func1(int a) {
cout << "func1" << endl;
}
void func2(int a) {
cout << "func2" << endl;
}
void func3(int a) {
cout << "func3" << endl;
}
typedef void (FuncTbl::*FuncPtr)(int a); // FuncTbl作用域内的函数指针
// or using FuncPtr = void (FuncTbl::*)(int a);
static FuncPtr ptr[];
void callFunc(int a) {
for (int i = 0; i < 3; i++) {
(this->*ptr[i])(a);
}
}
};
// 静态表驱动在类外声明
FuncTbl::FuncPtr FuncTbl::ptr[] = { &FuncTbl::func1, &FuncTbl::func2, &FuncTbl::func3};
int main() {
FuncTbl f;
f.callFunc(1);
return 0;
}
2. 非静态成员函数,非静态表
class FuncTbl {
public:
void func1(int a) {
cout << "func1" << endl;
}
void func2(int a) {
cout << "func2" << endl;
}
void func3(int a) {
cout << "func3" << endl;
}
// 表 和 typedef也可以在方法内声明
typedef void (FuncTbl::*FuncPtr)(int a);
// or using FuncPtr = void (FuncTbl::*)(int a);
FuncPtr ptr[3] = { &FuncTbl::func1, &FuncTbl::func2, &FuncTbl::func3};
void callFunc(int a) {
for (int i = 0; i < 3; i++) {
(this->*ptr[i])(a);
}
}
};
int main() {
FuncTbl f;
f.callFunc(1);
return 0;
}
3. bind绑定对象
class FuncTbl {
public:
void func1(int a) {
cout << "func1:" << a << endl;
}
void func2(int a) {
cout << "func2:" << a << endl;
}
void func3(int a) {
cout << "func3:" << a << endl;
}
typedef void (FuncTbl::*FuncPtr)(int a);
FuncPtr ptr[3] = {&FuncTbl::func1, &FuncTbl::func2, &FuncTbl::func3};
void callFunc(int a) {
for (int i = 0; i < 3; i++) {
(this->*ptr[i])(a);
}
}
void callFuncByBind(int a) {
function<void(int)> f[3] = {
bind(&FuncTbl::func1, this, placeholders::_1),
bind(&FuncTbl::func2, this, placeholders::_1),
bind(&FuncTbl::func3, this, placeholders::_1)
};
for (int i = 0; i < 3; i++) {
f[i](a++);
}
}
};
int main() {
FuncTbl f;
f.callFunc(1);
f.callFuncByBind(0);
return 0;
}
感觉个人比较推荐第二种写法。用bind写起来有点不好看,如果需要指定的参数很多,而且都不固定,写起来怪不好看的。
4.静态成员函数
这个写法其实和c里的表驱动没啥区别,函数指针换成了 &className::FuncName而已
5.lambda函数
class FuncTbl {
public:
void func1(int a) {
cout << "func1:" << a << endl;
}
void func2(int a) {
cout << "func2:" << a << endl;
}
void func3(int a) {
cout << "func3:" << a << endl;
}
void callFuncLambda(int a) {
function<void()> Func[] = {
[&]() { func1(a); },
[&]() { func2(a); },
[&]() { func3(a); }
};
for (int i = 0; i < 3; i++) {
Func[i](a);
}
}
};