1. 我们都知道,#define PRICE 30 是预编译处理器进行预编译的时候执行的,无法在编译器进行编译的过程中看见,因此,当编译出错的时候,通常错误信息是提到30,而不是PRICE,因此程序员很难定位到出错的位置。
解决方法是以const代替#define:const int Price = 30; Price肯定可以被编译器看到,因此不会导致上述错误。
2. 为了将常量的作用域限定于一个类中使用,并且只有一份数据,通常定义一个static成员变量(#define无法做到这点):
class A
{
private:
static const int Count = 5; // const声明式
int stu[Count]; // 使用该const
};
Count是一个声明式而非定义式,如果要使用定义式,通常定义如下:const int A::Count; // 不要赋值,因为声明时已赋初值。将定义式放在实现文件,而不是头文件中。
3. enum可以代替const在2中的实现, enum { Count = 5 }; 此外enum还可以约束Count不被pointer, reference所指向。这也是template metaprogramming的基础技术。
4. 关于#define的一个误用就是实现宏,macros看起来像个函数,但是不会导致函数调用带来的额外开销。
#define MAX(a, b) max( (a) > (b) ? (a) : (b)) // 千万不要忘记括号
光看到这个宏,我就头大了,除了会带来忘记括号的风险之外,还会产生你意想不到的错误结果:
int a = 3, b = 1;
MAX(++a, b) // a被累加2次
MAX(++a, b + 10) // a被累加1次
Oh,my god!!! a的累加次数竟然取决于a所比较的对象!!!通常为了避免错误,我们都是通过inline来实现的:
template <typename T> inline void Max(const T& a, const T& b)
{
f(a > b ? a : b);
}
怎么样,是不是轻松多了?此外还能设置inline的访问权限,#define永远都无法达到这点。
请记住:对于单纯的常量,最好用const, enum替换#define。
对于类似于函数的宏,最好用inline替换#define。