条款02:尽量以const,enum,inline代替#define
我们经常用define做什么?
1) 定义一个常量
2) 定义一个宏
为什么说尽量不用define。那么以这两个方面来解释:
1) 当我们定义一个常量时,我们可以用以下方式:
#define ASPECT_PATIO 1.653
我们知道编译器并没有看到ASPECT_PATIO符号(为什么?复习程序的预编译,编译,链接,运行)。于是这个记号ASPECT_PATIO并没有进行编译器的记号表内。恰巧如果我们获得了一个编译时期的错误,这个错误信息中会提到1.653而不是ASPECT_PATIO。这时,你会感到不解。
如果这个符号ASPECT_PATIO并没有定义在此文件内,则你就可能一头雾水。
引起这两种情况的原因都是:你所使用的名称可能未进入记号表。
怎么办?
我们可以用一个const常量来替换上面的宏。
Const double AsspectRation = 1.653;作为一个语言常量,它是被编译器看到,并记入符号表的。
用const 来代替define还有一个好处是可以定义一个类的专属常量。但是define没有类域的影响。
比如我们用const来定义一个类的专属常量 :
Class GamePlayer{
Static const int numTurns = 5;//这是声明,由于是整型常量,所以可以在类定义内给一个初始值。
}
Const int GamePlayer::numTurns; //这是numTurns的定义,由于之前给了初始值,这里不用再赋值了
如果你用define来定义一个常量,它不仅属于这一个类,也属于其他的类。没有封装性。
2) 定义一个宏
为什么用宏,因为宏看起来像函数,但是不会招致函数调用时带来的额外的开销。
比如定义一个两值取最大的宏
#define MAX(a,b) ( (a) >= (b) ? (a) : (b) )
这里一定要注意,宏中所有的实参要加上小括号,否则会有麻烦。
但是,我们可以用内联来消除这些隐患。
Template<class T>
Inline T MAX(const T& a, const T& b){
Return (a>= b ? a:b);
}
用内联的好处:没有调用函数时的开销,编译器可以对内联的代码进行优化。
问是不是 define就没有用了呢?
也不是的,有了const , inline使得我们对于预编译器(尤其是define)的需求降低了。但是并没有消除。#include是必需品,而#ifdef,#ifndef也继续扮演控制编译的角色。
请记住:
- 对于单纯常量,最好以const对象或enum来代替#define.
- 对于形似函数的宏,最好改用inline函数替换#defines.