尽量使用const、enum、inline来替换#define
前言
因为“#define”并不是语言的一部分,所以在一些情况下,“#define”并不是一个最佳的选择,甚至无出现意想不到的报错。
一、const替代#define
由于 #define 不是语言的一部分,所以也许在编译器开始处理源码之前就被预处理器移走了,于是就没有进入记号表内,所以在一些不够优秀的编译器内会报错,并且也很难对其追踪。
这时可用可用常量(const)来代替宏(#define)定义。
例如:
const double AspectRatio = 1.653;
define 可以用于全局变量,但是不可用于类成员变量的定义。而const可以用于类成员变量的定义。当为让类共享同一个常量,并且只有一份,在前面加static关键字修饰。
例如:
class GamePlayer{
private:
static const int NumTurns = 5; //常量声明式
int scores [NumTurns]; //使用该常量
...
};
在某些编译器中不支持static成员在其声明式上获得初值。这时处理方式为:
class CostEstimate {
private:
static const double FudgeFactor;// static class常量声明
//位于头文件内
};
const double CostEstimate: : FudgeFactor = 1.35;//static class常量定义,位于实现文件内
二、enum替代#define
enum在某些方面来说更像#define而不像const,例如:取一个const的地址是合法的,但取enum的地址就是不合法的,而取#define的地址也是不合法的。但是enum可以在类里面定义成员变量。理论为:一个属于枚举类型的数值可以充当 int 被使用。
例如:
class GamePlayer {
private:
enum { NumTurns = 5 };//令NumTurns成为5的一个记号名称.
int scores [NumTurns];//这就没问题了.
......
};
三、inline替代#define
#define 实现宏函数,这样不会招致函数调用带来的额外开销。并且在定义宏时,宏中的所有实参要加上小括号。有时纵使对所有实参加上了小括号,依然会出现意想不到不到的事情。
例如:
//以a和 b的较大值调用f
#define CALL_WITH_MAX(a, b) f=((a)>(b)? (a) : (b))
int a = 5, b = 0;
CALL_WITH_MAX(++a, b);//a被累加二次
CALL_WITH_MAX (++a,b+10);//a被累加一次
这时就可用inline替代#define来定义函数,inline不但可以实现同样的效率同时具有安全性。同时可以使用在类内。
例如:
template<typename T>
inline void callwithMax (const T& a,const T& b)
{
f (a > b ? a : b);
}
总结
- 对于单纯常量,最好以const对象或enums替换#defines。
- 对于形似函数的宏( macros),最好改用inline函数替换#defines。