首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

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

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

实在不想在此处用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 

热点排行