zoukankan      html  css  js  c++  java
  • 如果MFC的消息映射表需要排序...

    这是今天下班前和同事讨论的问题。

    MFC的消息映射通过几个简单的宏,对Windows的消息机制做了非常好的面向对象封装,一时为无数C++程序员所模仿(当然,MFC可能也是模仿别人的)。熟悉MFC消息映射机制的人都知道,其本质无非就是把消息和其处理函数放到一个数组当中,当程序接收到某消息时,就会遍历该数组,查找对应的消息ID,找到了就调用其处理函数,找不到就往其基类的数组当中去找。

    对,是线性查找!那么为什么MFC没有将消息数组排序,然后用二分查找,把复杂度从O(n)提高到O(lg n)呢?原因我想可能是没有必要,可以想像,一个类中的消息处理函数的个数是十分有限的,假设有100个消息,最坏情况也就是比较100个整数,其效率影响也是非常小的。而为了这不必要的效率在Framework级别加入排序与二分查找的算法,无疑增加了不必要的代码复杂度。

    那么假设现在让你实现对消息映射表的排序,该如何来做呢?

    因为消息映射表是全局变量,在Winmain之前就已经建好了,所以可以在Winmain的最开始做这个排序动作;但是MFC是封装了Winmain的,你无从修改,所以应该放在CWinApp::InitInstance()中;但是我们好像无法在这么一个统一的地方,访问到所有的MFC类的消息映射表并对其进行排序 - CRuntimeClass应该也无法完成这个任务,而且在非serialize的MFC程序中,其CRuntimeClass是没有连在一个链表中的,所以连访问CRuntimeClass都有问题。

    另外一个想法是在接收到一个消息之后,但在dispatch之前对消息映射表进行排序,这个地点就是CCmdTarget::OnCmdMsg,这是个好方法,只需对用到的那个类进行排序,有点lazy evaluation的味道。 但是我们不能每次调用都排序一遍,那就势必需要一个static的变量来标志该消息映射表是否有序,可以这么做,在message map的宏实现中,额外插入一个初始值为false的static bool变量,和一个Sort的虚函数用来对消息映射表进行排序(调用一个公用的排序函数),并设置标志位,这样在CCmdTarget::OnCmdMsg调用该Sort虚函数就完成了排序。但这样有个缺点,就是每个类都多了一个额外的虚函数,对size和performance都有些影响。其实我们还可以复用消息映射表来存储这个标志位 - 因为每个类都会对应一个消息映射表,所以只要在每个类的消息映射表的第一项插入是否有序的标志,在CCmdTarget::OnCmdMsg中直接通过GetMessageMap虚函数拿到当前类的消息映射表,检验第一项标志位是否为排序,如果为否则排序,否则继续,句号。当然,这里有一点要注意的是把消息映射表的第一项挪做他用了,Framework的其他地方不会误解而当做普通项来使用。

  • 相关阅读:
    光线投射算法与光线跟踪算法
    体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)
    体绘制(Volume Rendering)概述之3:光线投射算法(Ray Casting)原理和注意要点(强烈推荐呀,讲的很好)
    PCL学习笔记二:Registration (ICP算法)
    局部坐标系和全局坐标系
    Kinect for Windows SDK开发入门(十九):Kinect Fusion
    谈谈论文级别
    在Linux中搭建一个FTP服务器
    Java 编程实践
    Oracle数据库查询语句
  • 原文地址:https://www.cnblogs.com/baiyanhuang/p/1902654.html
Copyright © 2011-2022 走看看