const
#define ASPECT_RATIO 1.653
编译器在处理源码之前ASPECT_RATIO就被移走了,ASPECT_RATIO有可能也没有进入记号表(symbol table)。当你获得一个常量错误时,显示的是数字1.653而不是ASPECT_RATIO。如果ASPECT_RATIO是别人定义在头文件中,你就很难查找出1.653来自何处了。
我们可以使用一个常量区替换上述的宏(#define):
const double ASPECT_RATIO = 1.653;
首先,ASPECT_RATIO肯定会进入记号表。宏定义可能导致较多的码相对于常量,因为预处理器盲目的将宏名称ASPECT_RATIO替换为1.653。
当使用常量替换宏定义,需要注意两种情况:
- 定义常量指针(constant pointers)。由于常量定义式通常被放在头文件内(以便被不同的源码含入),因此有必要将指针(而不是指针所指之物)声明为const,并且需要两个const(例: const int * const a = &b,左边的const限定不能通过*a来改变b,右边的const限定 a不能指向别的值)
- class 专属常量。为了让常量的作用域(scope)限制于class内,你必须让它成为class的一个成员(member);而为确保此常量至多只有一份实体,你必须让它成为一个static成员。
#define定义的宏,在其后的编译过程中都是有效的(除非被#undef)。这意味着#defines不仅不能够用来定义class专属常量,也不能够提供任何封装性。
enum
在某些常量无法发挥作用的时候,就可以选择使用enum。
inline
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
无论何时当你写出这种宏,你必须记住为宏中所有实参加上小括号,否则某些人在表达式中调用这个宏时可能会遭遇麻烦(我也没懂这句话啥意思,欢迎大家不吝赐教)
所以可能写成inline+template形式
template<typename T>
inline void callWithMax(const T& a,const T& b){
}
请记住:
- 对于单纯常量,最好以const对象或enums 替换 #defines
- 对于形似函数的宏(macros),最好改用inline 函数替换#defines
本文主要内容来自于侯捷老师译的《Effective C++》,大力推荐感兴趣的同学可以去购买。也欢迎大家交流!