表驱动是一种很不错的编程方法,合理的使用表驱动能够极大的减少代码的复杂度,消除掉大量的if else或者是switch语句,并且能够提升代码性能。
因为哈希是最快的查找算法。这儿我只是给出如何在C++ 中使用表驱动的编程方法。
假设我们正在编写一个消息协议处理程序,需要处理不同协议的消息包,那么肯定会立即想到需要根据消息头中的协议字段来区分消息类型,并
发送到对应的消息处理函数中处理。
enum MsgType
{
PROTO_TCP,
PROTO_UDP,
PROTO_SCTP,
PROTO_NULL,
};
class Msg
{
public:
int type;
int size;
};
class MsgProc
{
public:
MsgProc();
~MsgProc();
int Proc(enum MsgType t, Msg* m);
private:
int TcpProc(Msg* m);
int UdpProc(Msg* m);
int SctpProc(Msg* m);
int ProcError(Msg* m);
private:
typedef int (MsgProc::*proc)(Msg* m);
struct tbl
{
enum MsgType msg_type;
proc msg_proc;
};
static struct tbl m_proc[];
};
这儿使用静态可变数组的方式实现,此种方法可能只是在GNU编译器上才是有效的。也可以使用map来保存,在构造函数中初始化表。但是毕竟map是红黑树实现占用的内存以及效率并没有静态数组高。
再给出CPP源程序的代码片段:
#include <iostream>
#include "msgproc.h"
using std::cout;
using std::endl;
struct MsgProc::tbl MsgProc::m_proc[] = {
{PROTO_TCP, &MsgProc::TcpProc},
{PROTO_UDP, &MsgProc::UdpProc},
{PROTO_SCTP, &MsgProc::SctpProc},
{PROTO_NULL, &MsgProc::ProcError},
};
MsgProc::MsgProc()
{
}
MsgProc::~MsgProc()
{
}
int MsgProc::TcpProc(Msg* m)
{
cout << "TcpProc:" << m->type << m->size << endl;
return 0;
}
int MsgProc::UdpProc(Msg* m)
{
cout << "UdpProc:" << m->type << m->size << endl;
return 0;
}
int MsgProc::SctpProc(Msg* m)
{
cout << "SctpProc:" << m->type << m->size << endl;
return 0;
}
int MsgProc::ProcError(Msg* m)
{
cout << "Error:" << endl;
return -1;
}
int MsgProc::Proc(enum MsgType t, Msg* m)
{
return (this->*m_proc[t].msg_proc)(m);
}
需要注意的是C++中对函数地址的引用和C语言不同,在调用表驱动函数的Proc成员函数中对表驱动方法的引用方式。