在读《Effective C++》之前,我确实不知道const,enum,inline会和define扯上什么关系,看完感觉收获很大,记录之。
define: 宏定义。 在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。由预处理器处理。
#define ASPECT_RATIO 1.653
记号名称ASPECT_RATIO也许从未被编译器看见,在编译器处理源代码之前就可能被预处理器移走了。于是记号就有可能没有进入到符号表中。(在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型、作用域以及内存地址)这样当使用该常量但获得编译错误信息时,错误信息可能只有1.653,而不会提到ASPCT_RATIO,而这个宏定义可能位于别人写的一个头文件中,这样你就无从查起,这个1.653是啥呢?Only God knows。 因为它可能没被记录到符号表中。
解决办法就是用一个常量替换上面的宏(#define)。
const double ASPECT_RATIO = 1.653
作为一个语言常量,肯定会被编译器看到,并被记录到符号表中。而且对于float型常量来说,使用常量会比使用宏定义需要更少的码,因为预处理器“盲目地将宏名称ASPECT_RATIO替换为 1.653可能会导致目标码(object code)中出现多份1.653”。若改用常量就不会出现这种情况。
用常量替换define需要注意的情况:
1. 定义常量指针
由于常量定义式通常位于头文件内(以便被不同的源码含入),因此有必要将指针声明为const。例如要在头文件内定义一个常量的char*字符串,需要写两个const。
const char* const authorName = "Scot Meryers"
第一个const表示指针指向的是一个常量字符串,不可以修改,第二个const表示该指针 authorName是一个const类型的指针,即指针也不能修改,不能让该指针指向其他字符串。
2. class专属常量
为了将常量的作用于限制于class内,必须让它成为class的一个成员;而为确保此常量只有一份实体,必须让它成为一个static成员。
class Gameplayer
{
private:
static const int NumTurns = ;
int scores[NumTurns];
//...
}
但VC编译器不支持这种行为:不允许static成员在声明式中获取初值(而gcc 4.6.3可以)。而数组在编译的时候必须指定大小,这个时候怎么办呢?可以用“enum hack”来补偿这一不足。 enum hack指的是不带实例的无标记的enum。 可以将 static const int NumTurns =5 替换为 enum {NumTurns=5};“enum hack”是模板元编程(template metaprogramming)的基础技术。
忠告:
1. 对于单纯常量,最好以const或者enum代替#define
2. 对于形似函数的宏,最好改用inline函数代替#define