当前位置: 首页 > news >正文

如果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的其他地方不会误解而当做普通项来使用。

 

相关文章:

  • 垂直搜索系统
  • Zend Studio下使用Zend Framwork框架开发配置步骤
  • 关于如何添加windows的性能计数器
  • 分享文档之中国1970年代经典相册(88张图片照射一个时代)
  • [转]了解AOP:来自程序员
  • 25招让男人精力旺旺
  • 紫狐浏览器,你的IPV6浏览器
  • C语言链表,多一个头结点
  • C#-Home 技术源料库
  • CentOS5.4安装配置dhcp服务器
  • CAN总线总结(5)——位定时,位同步的总结
  • 【百度地图API】情人节求爱大作战——添加标注功能
  • 业绩不是“看”出来的
  • js实现页面跳转的几种方式
  • freebsd下检测adsl线路的脚本
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【翻译】babel对TC39装饰器草案的实现
  • 10个确保微服务与容器安全的最佳实践
  • 2017年终总结、随想
  • HTTP 简介
  • npx命令介绍
  • SpringBoot几种定时任务的实现方式
  • text-decoration与color属性
  • uva 10370 Above Average
  • 产品三维模型在线预览
  • 关于springcloud Gateway中的限流
  • 回顾 Swift 多平台移植进度 #2
  • 记一次和乔布斯合作最难忘的经历
  • 软件开发学习的5大技巧,你知道吗?
  • 温故知新之javascript面向对象
  • linux 淘宝开源监控工具tsar
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • #13 yum、编译安装与sed命令的使用
  • (13)Hive调优——动态分区导致的小文件问题
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (笔试题)合法字符串
  • (附源码)计算机毕业设计高校学生选课系统
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)程序员疫苗:代码注入
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .jks文件(JAVA KeyStore)
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .net core 控制台应用程序读取配置文件app.config
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .net快速开发框架源码分享
  • .Net中ListT 泛型转成DataTable、DataSet
  • @Autowired和@Resource的区别
  • [ C++ ] 继承
  • [20150321]索引空块的问题.txt
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [BUAA软工]第一次博客作业---阅读《构建之法》
  • [BZOJ1877][SDOI2009]晨跑[最大流+费用流]
  • [C\C++]读入优化【技巧】