读书人

实在不想在此处用switch…有没有其他替

发布时间: 2013-03-20 15:25:24 作者: rapoo

实在不想在此处用switch…请教各位有没有其他替代品?
void MyClass::DispatchMessage(Message & msg)
{

Message是一个“消息参数”基类,其派生出“键盘消息” “鼠标消息”等类,

而当外部调用这个函数时,我不得不这样写,才知道传入了哪个参数:
switch(msg.MessageID)
{
case MID_KEYBOARD:
DispatchMessage(dynamic_cast<KeyboardMsg&>(msg));
………

请问有没有不用switch的办法?
[解决办法]

引用:
不知道能不能通过C++的重载等特性,用什么技巧把它给去掉?

因为将陆续添加各种不同的基于Message的参数,不想维护一个超长的switch代码块

我C++很烂…

那就维护一个消息map,通过循环来发送。

[解决办法]
直接用多态吧,试下 DispatchMessage 通过虚函数实现
[解决办法]
于是我邪恶地想起了《Modern C++ Design》里面的 dispatcher……
#include <typeinfo>
#include <map>
#include <iostream>

class TypeInfoWarpper
{
public:
TypeInfoWarpper(std::type_info const & info) : pTypeInfo(&info) {}
friend bool operator < (TypeInfoWarpper const& t1, TypeInfoWarpper const& t2)
{
return t1.pTypeInfo->before(*t2.pTypeInfo);
}
private:
std::type_info const * pTypeInfo;
};

class Base
{
public:
virtual ~Base() {}
};

class Sub1 : public Base
{
public:
virtual ~Sub1() {}
};

class Sub2 : public Base
{
public:
virtual ~Sub2() {}
};

void fun(Sub1 &)
{
std::cout<<"Sub1"<<std::endl;
}

void fun(Sub2 &)
{
std::cout<<"Sub2"<<std::endl;
}

template <typename Type>
void dispatcher_fun(Base & base)
{
fun(dynamic_cast<Type&>(base));
}

typedef std::map<TypeInfoWarpper, void (*)(Base&)> map_type;
map_type dispatcher_map;
typedef map_type::value_type value_type;

void dispatcher(Base & base)
{
dispatcher_map[typeid(base)](base);
}

int main()
{
dispatcher_map.insert(value_type(typeid(Sub1), dispatcher_fun<Sub1>));
dispatcher_map.insert(value_type(typeid(Sub2), dispatcher_fun<Sub2>));
Base * pBase1 = new Sub1;
Base * pBase2 = new Sub2;
dispatcher(*pBase1);
dispatcher(*pBase2);
delete pBase1;
delete pBase2;
return 0;


}


[解决办法]
用继承+接口+map实现,看这样子可以不:
//消息处理类基类
class EventInterface
{
public:
virtual void dealwithMsg(Message &msg)=0;
protected:
virtual void registerEvent(int id);
protected:
MyClass *m_pMyClass;
};
void EventInterface::registerEvent(int id)
{
m_pMyClass->RegisterEvent(id,this);//必须先获得m_pMyClass,可以用 全局变量 或 构造函数传入 等方法
}
//鼠标消息处理类
class MouseEventManager:public EventInterface
{
public:
MouseEventManager();
public:
virtual void dealwithMsg(Message &mouseMsg);
};
MouseEventManager::MouseEventManager()
{
registerEvent(MID_MOUSE);
}
void MouseEventManager::dealwithMsg(Message &mouseMsg)
{
;//处理鼠标信息
}
//键盘消息处理类
class KeyboardEventManager:public EventInterface
{
public:
KeyboardEventManager();
public:
virtual void dealwithMsg(Message &keyboardMsg);
};
KeyboardEventManager::KeyboardEventManager()
{
registerEvent(MID_KEYBOARD);
}
void KeyboardEventManager::dealwithMsg(Message &keyboardMsg)
{
;//处理键盘信息
}
//消息分发类
class MyClass
{
public:
void DispatchMessage(Message & msg);
void RegisterEvent(int id,EventInterface* pEvent);
private:
EventInterface *m_pEvent;
map<int,EventInterface*> msgMap;
};
void MyClass::DispatchMessage(Message & msg)
{
map<int, EventInterface*>::iterator iter=msgMap.find(msg.MessageID);//msg.MessageID);
if(iter!=msgMap.end())
{
m_pEvent=iter->second;
}
else
{
;//未注册消息可不做处理
return;
}
m_pEvent->dealwithMsg(msg);
}
void MyClass::RegisterEvent(int id,EventInterface *pEvent)
{
msgMap.insert(map<int, EventInterface*>::value_type(id, pEvent));
}
[解决办法]
的确巨大的switch 在 mainWndProc 中 看起来很不爽
想起一个在 windows CE 的做法---用for 来代替


// 维户数组长度
#define dim(x) (sizeof(x) / sizeof(x[0]))

// 消息关联结构
struct MsgAss
{
UINT code;
LRESULT (*fxn)(hwnd,....);
};

// 注册: 消息与处理函数关联
const struct MsgAss mainMessages[] = {
WM_PAINT, paint_Proc,
WM_XXXX, xxxxx_Proc,
...
}


//消息处理 mainWndProc:
//..
for (int i=0; i<dim(mainMessages); ++i)
{
if (wMsg == mainMessages[i].code)
return (mainMessages[i].fxn)(hWnd, wMsg, ......);
}
//..

// 如果再封装成 单件类 看起来会很优雅
// 传说中这种写法出于一大牛: Ray Duncan

读书人网 >C++

热点推荐