说到宏,恐怕大家都能说出点东西来:一种预处理,没有分号(真的吗?)。然后呢?嗯.......茫然中......好吧,我们就从这开始说起。
最常见的宏恐怕是#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()
{
  ;
  cout<<A()<<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

浅析 C++里面的宏的更多相关文章

  1. QVariant(相当于是Java里面的Object,起到一个数据类型“擦除”的作用,可以使用Q_DECLARE_METATYPE进行注册)

    =QVariant= [%这个类型相当于是Java里面的Object,它把绝大多数Qt提供的数据类型都封装起来,起到一个数据类型“擦除”的作用.比如我们的 table单元格可以是string,也可以是 ...

  2. QVariant(相当于是Java里面的Object,是万能的容器,但要注册)

    这个类型相当于是Java里面的Object,它把绝大多数Qt提供的数据类型都封装起来,起到一个数据类型“擦除”的作用.比如我们的 table单元格可以是string,也可以是int,也可以是一个颜色值 ...

  3. Activity往另外一个Activity传值,Fragment获取另外一个Activity里面的值。

    在oneActivity中实现跳转到MainActivity //intent 用来跳转另外一个MainActivity,bundle传值到MainActivity         Intent Ma ...

  4. Java基本概念(2)J2EE里面的2是什么意思

    J2EE里面的2是什么意思 J2SE,J2SE,J2ME中2的含义要追溯要1998年.1998年Java 1.2版本发布,1999年发布Java 1.2的标准版,企业版,微型版三个版本,为了区分这三个 ...

  5. 在wex5平台grid里面的gridselect下拉不能显示汉字问题

    当grid里面有gridSelect组件的时候,gridSelect里面的bind-ref是对应的数据库存入字段(int类型),bind-labelRef是对应的计算字段(视图里面的),而option ...

  6. dede文章调用时过滤调 body里面的style属性和值

    dede 发布文章的时候会在里面的标签中添加一些style 属性,现在改网站想去掉这些属性和里面的值,因为文章太多所以就用下面的方法 \include\arc.listview.class.php 在 ...

  7. 提取数据库字段里面的值,并改变+图片懒加载,jquery延迟加载

    要求:手机端打开某个页面的详细信息,因为网速或者别的原因,响应太慢,因为图片大的原因,希望先进来,图片在网页运行的情况再慢慢加载(jquer延迟加载) http://www.w3cways.com/1 ...

  8. JAVA里面的IO流(一)分类2(节点流和处理流及构造方法概要)

    IO流根据处理对象的不同分为节点流和处理流. 直接对文件进行处理的流为节点流: 对流进行包装从而实现对文件的优化处理的流为处理流. 节点流类型: 可以看出,节点流主要分这几大类: 文件流 文件流构造方 ...

  9. 头文件里面的ifndef /define/endif的作用

    c,c++里面,头文件里面的ifndef /define/endif的作用 今天和宿舍同学讨论一个小程序,发现有点地方不大懂······ 是关于头文件里面的一些地方: 例如:要编写头文件test.h ...

随机推荐

  1. dataGridView行高自适应

    今天从网上查询相关datagridview行高自适应的信息时,好多都是告诉你直接用下面三行代码: dataGridView1.AutoSizeRowsMode = DataGridViewAutoSi ...

  2. JS中各种宽度、高度、位置、距离总结

    1.window.screen 浏览器与屏幕的距离,screenX(screenLeft),screenY(screenTop) 2.window.scrollTo(x,y) 将纵向滚动条移动到相对于 ...

  3. LUN----逻辑单元号

    LUN的全称是Logical Unit Number,也就是逻辑单元号.   一.概念   LUN的全称是Logical Unit Number,也就是逻辑单元号.我们知道SCSI总线上可挂接的设备数 ...

  4. 有意思的GacUI

    所有方法,无论是你写还是工具来codegen还是用宏,最终都指向把这些名字和对应的指针存在一个map里.C++是不提供这个功能的,我也没仔细研究过qt怎么做,不过我在我自己的gacui里面实现了类似的 ...

  5. windows bat脚本编写

    windows批处理 (cmd/bat) 编程详解 开始之前先简单说明下cmd文件和bat文件的区别:在本质上两者没有区别,都是简单的文本编码方式,都可以用记事本创建.编辑和查看.两者所用的命令行代码 ...

  6. 51 EEPROM操作模板

    各个型号容量及扇区请查datasheet #include <reg52.h> #include "intrins.h" typedef unsigned char b ...

  7. Hibernate 配置详解(8)

    hibernate.generate_statistics 这个配置大家应该都很熟悉,用于开启Hibernate统计信息,便于对Hibernate相关性能调试提供数据依据.在开发过程当中,可以把这个选 ...

  8. javaWeb Cache技术――OSCache(转-全)

    什么是osCache? 它是:http://baike.baidu.com/view/1835163.htm?fr=aladdin OSCache使用指南 一.下载安装 OSCache是一个基于web ...

  9. JavaEE Tutorials (29) - Duke辅导案例研究示例

    29.1Duke辅导应用的设计和架构44529.2主界面447 29.2.1主界面中使用的Java持久化API实体447 29.2.2主界面中使用的企业bean448 29.2.3主界面中使用的Web ...

  10. JavaEE Tutorials (28) - Duke书店案例研究示例

    28.1Duke书店的设计和架构43828.2Duke书店接口439 28.2.1Book Java持久化API实体439 28.2.2Duke书店中使用的企业bean440 28.2.3Duke书店 ...