条款1:尽量用 const 和 inline 而不用#define 这个条款最好称为:"尽量用编译器而不用预处理"。因为#define 经常被认为好像不是语言本身的一部分。这是问题之一。 另外,再看下面的语句:#define PI 3.1415926 1.编译器永远看不到 PI 这个符号名,因为在源码进入编译器之前,它会先被预处理程序去掉,于是 PI不会加入到符号列表中。 2.如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息会指向 3.1415926,而不是PI。 3.这个问题也会出现在符号调试器中,因为PI不会出现在符号列表中。 解决方案: 不用预处理宏,定义一个常量。 const double PI = 3.1415926; 但有两个特殊情况要注意。 :定义指针常量时会有点不同 因为常量定义一般是放在头文件中(许多源文件会包含它),除了指针所指的类型要定义成 const 外,重要的是指针也是经常要定义成 const。例如: const char * const AUTHOR_NAME = "Scott Meyers"; //Scott Meyers是本书的作者名 关于 const 的含义和用法,特别是和指针相关联的问题,参见条款 21。定义某个类的常量一般也很方便,只有一点点不同。 要把常量限制在类中,首先要使它成为类的成员;为了保证常量最多只有一份拷贝,还要把它定义为静态成员。class GamePlayer { private: /* *1.只有static const int 3个关键字同时出现时才能在声明时初始化。 *2.static const double NUM_TURNS 声明常量时,只能在定义时初始化(cpp文件中)。 */ static const int NUM_TURNS = 5; int scores[NUM_TURNS]; ... }; 还必须在cpp文件中定义类的静态成员。const int GamePlayer::NUM_TURNS; //cpp文件中进行常量定义 注意: 上面 GamePlayer::scores 数组的声明(编译过程要确定数组的大小),如果有些编译器不支持类内进行整型类常量初始化,我们就需要使用枚举enum来替代const。class GamePlayer { private: enum { NUM_TURNS = 5 }; int scores[NUM_TURNS]; ... }; 回到预处理的话题上来。另外一个普遍的#define 指令的用法是用它来实现那些看起来像函数而又不会导致函数调用的宏。典型的例子是计算两个对象的最大值: #define max(a,b) ((a) > (b) ? (a) : (b)) 这个语句有很多缺陷,光想想都让人头疼,甚至比在高峰时间到高速公路去开车还让人痛苦。无论什么时候你写了像这样的宏,你必须记住在写宏体时对每个参数都要加上括号;否则,别人调用你的宏时如果用了表达式就会造成很大的麻烦。 解决方案: inline int max(int a, int b) { return a > b ? a : b; } 但这个版本的 max 却只能处理 int 类型。进一步的解决方案是使用模板。 templateinline const T& max(const T& a, const T& b) { return a > b ? a : b; } 因为不知道 T 的类型,返回时传引用可以提高效率(见条款 22)。 提醒一点是,在你打算用模板技术自己造轮子时,先检查下标准库(见条款 49),因为很多功能都已经是C++标准库的一部分了,max早已经存在于标准库中。