这个条款等价于“尽量使用编译器而不用预处理”
改进1:
#define PI 3.1415
在C++的编译器中,看不到PI这个符号名,因为源码在进入编译器之前就已经被预处理了。PI不会进入符号列表。涉及这个常量的报错,编译器会指向3.1415,而不是PI,会给我们在调试时带来麻烦。
解决的方法:不用宏,定义一个const常量
const double PI = 3.1415;
定义时有两点的注意:
1.定义指针常量会有点不同。例如定义一个基于char*的字符串常量,需要写两次const
const char* const authorName = "Scott Meyers";
2.定义某个class类的常量也非常方便,只是有一点点不同。要把常量放在类中,首先让它成为类的成员;为了保证常量最多有一次拷贝,还要把它定义成为static静态成员:
class GamePlayer {
private:
static const int NUM_TURNS = 5; // const declaration
int scores[NUM_TURNS];
...
};
上面的NUM_TURNS是声明,而不是定义,所以我们需要在类的实现中定义类的静态成员:
const int GamePlayer::NUM_TURNS; //mandatory definition;
// goes in class impl.file
改进2:
另一个普遍的#define指令的用法是用它来实现那些看起来像函数而不会导致函数调用的宏。典型的例子就是计算两个对象的较大值:
#define max(a,b) ((a) > (b) ? a : b)
这个语句有很多的缺陷。就是你无论什么时候写了这样的宏,你必须记住在写宏体时要对每个参数加括号;否则,别人调用你的宏时如果用了表达式就会造成很大的麻烦。
即使如此,也会有意料之外的发生:
int a = 5, b = 0;
max(++a, b); //a的值加了2次
max(++a, b+10)// a的值加了1次
解决的方法是使用inline函数,仅仅需要普通函数的效率和可预计的行为和类型安全。
inline int max(int a, int b) { return a > b ? a : b}
不过这个函数只能处理int型的max函数,可以使用模板template来解决这个问题:
template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b}
这个模板函数产生了一系列的函数,每个函数可以转换成同种类型的对象进行比较然后返回较大对象的引用。因为不知道T的类型,可以使用传递引用来提高效率
有了const和inline,可以减少预处理