尽量以const , enum,inline 代替 #define;
例1:
#define Aspect _ratio 1.653
名称Aspect_ratio也许未被编译器看见:在编译器开始处理源码之前就被预处理器移走。
所以Aspect_ratio可能没进入Symbol table(记号表)。当运用此变量在编译出错时会得到一个提到1.653而不是Aspect_ratio的编译错误信息。
若此情况发生在头文件中,会因为追踪它而浪费时间。
解决方法:
以一个常量代替上诉的宏:const double AspectRatio=1.653;
此时AspectRatio作为一个语言常量,肯定会被编译器看到,自然会进入记号表,也可能使用较少量的码。
若以常量替换#define,两种情况值得说:1,定义常量指针在头文件内,有必要将指针声明为const:const char* const authorName="Scott Meyers".另外,用string对象更适宜:const std::string AuthorName("Scott Meyers");
2,#define 不仅不能够用来定义class专属常量,也不能够提供任何封装性:因为#define并不重视作用域,一旦其被定义,就在后面的编译过程中有效(除非在某处被#undef)。万一编译器不允许"static 整数型class常量"完成“in class 初值设定”
例:
Class GamePlayer{
Private:static const int NumTurns=5;
......
}
, 可改用所谓的"the enum hack“补偿做法:(一个属于枚举类型的数值可权充ints被使用)
例: class GamePlayer{
private:
enum{NumTurns=5};
//“the enum hack” 让NumTurns成为5的一个记号名称
int scores[NumTurns];
....
}
如果你不想让别人获得一个pointer或reference指向你的某个整数常量,enum可以帮助实现这个约束)
另外常见的#define误用情况是以它实现宏(宏看起来像函数,但不会招致函数调用带来的额外开销)
例:
#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 被累加了一次
可用template inline 函数来避免这一切且获得宏带来的效率和一般函数的所有可预料行为和类型安全性:
template<typename T>
inline void callwithMax(const T& a ,const T& b){
f(a>b? a : b);
}