ITPub博客

首页 > 应用开发 > IT综合 > 浅析C++里面的宏 (转)

浅析C++里面的宏 (转)

原创 IT综合 作者:gugu99 时间:2007-08-15 14:14:03 0 删除 编辑
浅析C++里面的宏 (转)[@more@]

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

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

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

3、代码版本管理。例如:
  #ifdef DEbug
  试版本
  #else
  调试版本
  #endif;

4、声明宏。例如:
  #define DECLARE_MESSAGE(x) x();~x()  没有分号?哈哈
  //........
  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
  #define A(x) ((x)>0? (x):-(x))

  void main()
  {
 int i=-1;
 cout< cout<  }
  有问题了,不过以后再说,大概讲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 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
  T ABS(const T& t) { return t>0 ? t : -t;  }
  template
  Class Stack  {  ............  };

  4、最后对于语法扩展程序几乎都可以用一个或多个C++类代替:
  Set s;
  int i;
  Set_iter 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。 


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10748419/viewspace-958131/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    3121
  • 访问量
    2643809