重温了一下 Effective C++,发现这就是条款24所指出的问题,看来读书百遍不如写代码一遍啊

在Notify处理消息时会有很多if语句,我通常喜欢把常量放在双等号前面,变量放在后面,比如:
    if( _T("click") ==  msg.sType )
    {
    }
    但是却发现并没有进到这个if里,调试发现,将常量调到前面时,并没有进入到CDuiString重载的 == 函数里面,所以这里必须将常量放到后面。
    if( msg.sType == _T("click") )
    {
    }
 
    这个bug的原因是因为将常量放在前面时,并没有调用CDuiString重载的 == 函数,而是调用了CDuiString重载的 ()函数,然后用系统自带的==函数做比较,而系统自己的==函数只是比较两个指针的首地址是否相等。_T("click") 的首地址指向的是一块临时变量,而msg.sType 是返回了CDuiString里面那个字符串的指针,很显然这两个指针地址是不相等的,所以我们只能把它放在前面,或者直接调用_tcscmp
    if( ! _tcscmp( _T("click"), msg.sType) )
    {
    }
 
    当然,如果要解决这个bug,就要重载多个==操作符,
    由于CDuiString是将==函数作为成员函数重载的,所以只有CDuiString对象在操作符左边时,才会调用这个重载函数,如果想要CDuiString对象在右边时也能调用重载的==函数,那么必须将重载操作符放到外部。这里我们可以看一下MFC的CString是怎么重载的:
    CString 重载了5个==操作符,都是友元函数,定义在#include<cstringt.h>里面。
    再看下STL的std::string :
    std::string重载了3个==操作符,都是全局函数,定义在#include<string>里面。
 
  不过需要提醒的是,我稍微看了下CDuiString的代码,有很多漏洞,比如在清零字符串时,只是调用了 m_szBuffer[0] = '\0'; 并不是调用memset,那么就会有以下问题,我们随意现在用下面两种方式给CDuiString 附值,然后监视字符串数组的内容,可以发现虽然显示是正确的,但是在零值后面的值全部是乱码:
 
 
    这样的话,虽然_tcslen、_tcscmp等函数能用,但是还有很多函数都会出问题的。
    所以这个CDuiString能不用则不用,如果嫌MFC生成的exe体积大,可以用WTL的CString,如果WTL也不想用,那就只好用STL的string了。
    当然,为了保证代码的兼容性,一些简单的处理还是用CDuiString比较好,比如 msg.sType。
    而逻辑处理等复杂的场景,最好用久经考验的代码。  虽然微软的CString很强大,而用STL的string时可能不方便,但是我现在越来越喜欢STL的string啦,当然,我是定义了一个string_t,加上一个名字空间,以防和一些开源库冲突,
    一些著名的开源库喜欢如下定义:
#ifdef _UNICODE
typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > string_t;
#else
typedef std::basic_string<char, std::char_traits<char>, std::allocator<char> > string_t;
#endif

不过我喜欢更简短的定义:

#ifdef _UNICODE
typedef std::wstring string_t;
#else
typedef std::string string_t;
#endif

下面是我常用的Unicode定义:

#include <string>
#include <sstream> namespace duilib
{
#ifdef _UNICODE
typedef wchar_t char_t;
typedef std::wstring string_t;
typedef std::wstringstream stringstream_t;
#else
typedef char char_t;
typedef std::string string_t;
typedef std::stringstream stringstream_t;
#endif
}
原文:http://www.cnblogs.com/Alberl/p/3344886.html

最新文章

  1. VMware安装CentOS时,无法以图形界面安装解决办法
  2. asp.net mvc4 学习笔记一(基本原理)
  3. 登录到mysql查看binlog日志
  4. 使用Spring Security Oauth2完成RESTful服务password认证的过程
  5. C++四种强转
  6. [HTML]页面间传值的五种方法
  7. HDU 5700 区间交 线段树暴力
  8. LNMP一键安装包-CentOS 5/6下自动编译安装Nginx,MySQL,PHP
  9. HADOOP在处理HIVE时权限错误的解决办法
  10. Apache Hadoop最佳实践和反模式
  11. Smarty注释代码
  12. SpringMVC数据绑定
  13. 配置HAProxy支持https协议
  14. mysql的存储过程,函数,事件,权限,触发器,事务,锁,视图,导入导出
  15. EFCore合并多条迁移记录
  16. FB面经Prepare: Merge K sorted Array
  17. 超级好看!巧用PS将风光人像打造成唯美的小星球效果!
  18. POJ 2498
  19. Python学习手冊笔记
  20. 搭建kafka高级消费 (high-consumer)php7

热门文章

  1. PHPExcel 对xls表格的文件读取
  2. MS SQL 日常维护管理常用脚本
  3. [转载]一种高性能Hierarchical RBAC实现方案
  4. unity文件写入与读取
  5. Python unittest 参数化
  6. JS高程3:函数表达式
  7. linux学习笔记15--命令locater、slocate
  8. FirstLetterUtil
  9. java对象实现深复制的方法
  10. libubox