现在的位置: 首页 > 综合 > 正文

如何写优雅的代码(5)–不一样的类用法

2013年04月23日 ⁄ 综合 ⁄ 共 2711字 ⁄ 字号 评论关闭

 

//=====================================================================
//TITLE:
//    如何写优雅的代码(5)--不一样的类用法
//AUTHOR:
//    norains
//DATE:
//    Tuesday 20-April-2010
//Environment:
//    Visual C++ 2005
//=====================================================================

 

    作为本文的楔子,提出一个问题:如何计算程序运行时某个API函数的实际调用次数?再具体一点来说,有个大家都熟悉的API函数GetParent,我们如何统计它在我们代码中被调用的次数?

 

    最简单的做法,可能大家都能想得出来,声明一个全局变量,在每次调用前都自增加一次。这个做法在调用函数次数比较少的情况下,的确无伤大雅;但如果是有上百处,是不是打算在这上百处前都添加一句自增的语句?更为糟糕的是,如果这个统计仅仅是在Debug时使用,正式发布时需要去掉,打算怎么弄?在编译之前手工删掉的方式我估计谁都不会用,估计大家都会想到宏定义,比如:

  1. #ifdef _DEBUG   
  2.   g_iCount ++;  
  3. #endif   
  4.   hWndParent = GetParent(hWnd);  

 

  看起来问题是解决了,但实际上引入的麻烦却不少:我们如何确定每次调用前都自增了一次?--特别是日后添加的调用代码,添加的人可能是自己,也可能是同事,如何保证会在调用之前还记得这个无关紧要的自增宏呢?
  
  这还不是最麻烦的,如果我们需要统计的函数不止一个,那么每增加一个统计如上的麻烦将增加一倍。我想,这是谁都无法接受的
  
  其实解决的方法很简单,C++不是有个函数的重载么?我们将GetParent直接重载不就可以了么?当然了,这个还有一个小小的限制,就是代码必须是以类为基础的。方法很简单,我们可以声明一个基类,然后在这个类里面重载GetParent,最后别的类派生于该类即可。
  
  根据此思想,我们声明一个基础类:
  

  1. class CBaseFunc  
  2. {  
  3. public:  
  4.  CBaseFunc(){}  
  5.  virtual ~CBaseFunc(){}  
  6.   
  7. private:  
  8.  static HWND GetParent(HWND hWnd)  
  9.  {  
  10.   ++ ms_dwCount;  
  11.   return ::GetParent(hWnd);  
  12.  }  
  13.   
  14. private:  
  15.  static DWORD ms_dwCount;  
  16. };  
  17.   
  18.      DWORD CBaseFunc::ms_dwCount = 0;  

  
  我们其它类都继承于该类:

  1. class CMonitor:  
  2.  public CBaseFunc  
  3. {  
  4. public:  
  5.  CMonitor(){};  
  6.  virtual ~CMonitor(){};  
  7. };  


  
  就是这么简单,我们不用担心忘记添加宏,不用麻烦地修整原来的代码,我们只需要一个基础类,一个不加::前缀的API函数调用,仅此而已。
  
  统计只不过是我们的一个应用,重载带来的好处并不仅限于此,我们可以在API函数调用前做太多事情,只要不缺乏想象力。
  
  比如说,CloseHandle这个API函数,我们都知道,如果同一句柄被重复关闭,那么会导致溢出。如果在执行前,我们能判断该句柄之前是否已经被关闭,而后才调用CloseHandle就好了。如果我们在基类中重载该函数,那么这也不是大问题:
  

  1.   class CBaseFunc  
  2.   {  
  3.   public:  
  4.    CBaseFunc(){}  
  5.    virtual ~CBaseFunc(){}  
  6.     
  7.     
  8.   private:  
  9.    static BOOL CloseHandle(HANDLE hObject)  
  10.    {  
  11.     //IsCloseBefore是我们自己定义的一个检查句柄的函数
      
  12.     if(IsCloseBefore(hObject) == FALSE)  
  13.     {  
  14.      return ::CloseHandle(hObject);  
  15.     }  
  16.     else  
  17.     {  
  18.      return FALSE;  
  19.     }  
  20.    }  
  21.   };  
  22.     

  
  也许有人看到这里会问,能不能不使用类,直接声明同名同形参的函数呢?答案是否定的,因为编译器会抱怨。
  
  函数重载,在很多时候,带给我们的惊喜远比想象的多。很多的解决方法,可以完全抛弃类;但使用类,却能带给我们更多的便捷,为什么我们还要拒绝它呢?

抱歉!评论已关闭.