zoukankan      html  css  js  c++  java
  • C++中的宏浅析

    C++中的宏浅析

    说到宏,恐怕大家都能说出点东西来:一种预处理,没有分号(真的吗?)。然后呢?
    嗯.......茫然中......
    好吧,我们就从这开始说起。
    最常见的宏恐怕是#include了,其次就是#define还有.......
    还是从宏的用途分类吧:

    1、#include 主要用于包含引用文件,至今其地位无人能替代;

    2、注释掉代码。例如:
       #if 0
       .......
       #endif;
       这种机制是目前注释掉代码的最佳选择,为摩托罗拉公司员工所普遍采用;

    3、代码版本管理。例如:
       #ifdef DEBUG
       file://调试版本
       #else
       file://非调试版本
       #endif;

    4、声明宏。例如:
       #define DECLARE_MESSAGE(x) x();~x()   file://有没有分号?哈哈
       //........
       class A
       {
       public:
               DECLARE_MESSAGE(A);
       ..............
       }
       想起什么了,呵呵:)对,VC里面有好多这样的东东,有空我会写《我的VC历程》,到
    时候会把VC里的各种宏详细的解释一下,那可是一个庞大的工程:)

    5、符号常量。例如:
       #define PI 3.14159

    6、内联函数。例如:
       #define CLEAR(x) ((x)=0)

    7、泛型函数。例如:
       #define ABS(x) ((x)>0? (x):-(x))
       x=3 没问题! x=1.3 也没问题!
       如果是这样呢:
       #include <iostream.h>
       #define A(x) ((x)>0? (x):-(x))

       void main()
       {
     int i=-1;
     cout<<A(1)<<endl;
     cout<<A(++i)<<endl;
       }
       有问题了,不过以后再说,大概讲const or inline 时会说的:)

    8、泛型类型。例如:
       #define Stack(T)  Stack__ ##T
       #define Stackdeclare(T)  class Stack(T) {.....}
       Stackdeclare(int);
       Stackdeclare(char);
       .......
       Stack(int) s1;
       Stack(char) s2;

    9、语法扩展。例如:
       Set<int> s;//假设Set为一个描述集合的类
       int i;
       FORALL(i,s);
       .......

      宏最大的问题便是易引起冲突,例如:
      libA.h:
       #define MACRO stuff
      同时:
      libB.h:
       #define MACRO stuff
      下面我们对他们进行引用:
      user.cpp:
       #include "libA.h"
       #include "libB.h"
      .............
       糟糕,出现了重定义!
      还有一种冲突的可能:
      libB.h:(没有定义宏MACRO)
      class x   { void MACRO();  ...........};
      那么程序运行期间,libA.h中的宏讲会改变libB.h中的成员函数的名字,导致不可预料
    的结果。
      宏的另一个问题,便是如7中出现的问题,如果你把7中的x设为'a',程序也不会给出任
    何警告,所以他是不安全的。
      针对以上的问题,我们说:
      1、尽可能的少用公用宏,能替换掉就替换掉;
      2、对那些不能替换的宏,使用命名约定;

       1、符号常量预处理程序我们可以用const or enum 来代替:
          const int TABLESIZE=1024;
          enum {  TABLESIZE=1024  };

       2、非泛型内联函数的预处理程序可以使用真正的内联函数来代替:
          inline void clear(int& x) {x=0;}
          奥,对了,还有这样一种情况:
          #define  CONTROL(c)  ((c)-64)
          ..........
          switch(c)
          {
             case CONTROL('a') :  ......
             case CONTROL('b') :  ......
             case CONTROL('c') :  ......
             case CONTROL('d') :  ......
             ..........
          }
          这时候就不能单独使用内联函数来取代了,因为case标签禁止函数调用,我们只好
    做如下转换:
          inline char control(char c) { return c+64; }
          ...........
          switch(control(c))
          {
            case 'a':.....
            case 'b':.....
            case 'c':.....
            case 'd':.....
            ........
          }
          当然这样做是以牺牲时间作为代价的(你想想为什么:))

       3、对于泛型预处理程序,我们可以用函数模板或类默板来代替:
          template<class T>
          T ABS(const T& t) { return t>0 ? t : -t;  }
          template<class T>
          Class Stack   {  ............   };

       4、最后对于语法扩展程序几乎都可以用一个或多个C++类代替:
          Set<int> s;
          int i;
          Set_iter<int> iter(s);
          while(iter.next(i))
          ...........
          与使用宏相比,我们只是牺牲了一点程序的简洁性而已。

       当然并不是所有的宏都能替换(我们也并不主张替换掉所有的宏!),对于不能替换的
    宏,我们应该对他们实行命名约定,例如:
         #define COMPANY_XYZ_LIBABC_MACRO stuff
        同时我们也要采取一定的方法,进行预防:
         #ifndef COMPANY_XYZ_LIBABC_MACRO
         #define COMPANY_XYZ_LIBABC_MACRO stuff
         #endif
        当然,在程序库实现内部定义的宏没有这个约束:
         my.cpp:
         #define MACRO stuff
         ........

       我们给出几个常见的宏: 
       #define  A(x)    T_##x
       #define  Bx)    #@x
       #define  Cx)    #x
       我们假设:x=1,则有:
       A(1)=======T_1
       B(1)======'1'
       C(1)======"1"
       还有一个比较常见的宏:_T
       TCHAR tStr[] = _T("t code");
       _T宏的作用就是转换成TCHAR。

  • 相关阅读:
    ASP.NET,flexpaper,SWFTools 实现简单的PDF显示(一)
    ASP.NET,flexpaper,SWFTools 实现简单的PDF显示(三)
    一个获取远程客户端真实IP的例子
    用微软Chart制作图表
    快速读取xml节点内容
    ASP.NET 网站路径【摘自MSDN】
    SqlServer连接字符串相关记录
    视图研究一二
    天大计算机研究生的求职总结
    一个计算机系研究生毕业以后的人生规划(转)
  • 原文地址:https://www.cnblogs.com/davidshi/p/3349092.html
Copyright © 2011-2022 走看看