c++表驱动

表驱动:

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);
        }
    }
};
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值