1 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#define不被视为语言的一部分。那正是它的问题所在。
2 const
#define ASPECT_RATIO 1.653
问题:记号名称ASPECT_RATIO也许从未被编译器看见。于是记号名称ASPECT RATIO有可能没进入记号表< symbol table)内。
改为:const double AspectRatio=1.653; //大写名称通常用于宏,因此这里改变名称写法。
注意:
1)常量指针(constant pointers):
由于常量定义式通常被放在头文件内,因此有必要将指针(而不只是指针所指之物)声明为const,例如若要在头文件内定义一个常量的char*-based字符串,你必须写cons两次:
const char* const authorName = "Scott Meyers";
const std::string authorName("Scott Meyers"); //string更合适
2)class专属常量:
为了将常量的作用域(scope)限制于class内,你必须让它成为class的一个成员(member);而为确保此常量至多只有一份实体,你必须让它成为一个static成员:
class GamePlayer{
private:
static const int NumTurns = 5; //常量声明式
int scores[NumTurns]; //使用该常量
};
通常C++要求你对你所使用的任何东西提供一个定义式,但如果它是个class专属常量又是static且为整数类型(integral type,例如rots, chars, bools ),则需特殊处理。只要不取它们的地址,你可以声明并使用它们而无须提供定义式。但如果你取某个class专属常量的地址,或纵使你不取其地址而你的编译器却(不正确地)坚持要看到一个定义式,你就必须另外提供定义式如下:
const int GamePlayer::NumTurns; //NumTurns的定义;
请把这个式子放进一个实现文件而非头文件。由于class常量己在声明时获得初值(例如先前声明NumTurns时为它设初值5),因此定义时不可以再设初值。
3 enum
the enum hack:如果编译器(错误地)不允许“static整数型class常量”完成“in class初值设定”,可改用所谓的”the enum
hack”补偿做法。其理论基础是:“一个属于枚举类型(enumerated type)的数值可权充ints被使用”,于是GamePlayer可定义如下:
class GamePlayer{
private:
enum{NumTurns = 5};//"the enum hack',令NumTurns成为5的一个记号名称。
int scores[NumTurns]; //这就没问题了。
}
enum hack特征:比较像#define而不像const,例如取一个const的地址是合法的,但取一个enum。的地址就不合法,而取一个#define的地址通常也不合法。
enum hack是template metaprogramming(模板元编程)的基础技术。
4 inline
#define用了实现宏(macros),看起来像函数,不会带来函数调用开销。
//以a和b的较大值调用f
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
注意:书写宏时,为所有实参加上小括号。
问题:
int a=5, b=0;
CALL WITH MAX(++a, b);//a被累加二次
CALL WITH MAX(++a, b+10);//a被累加一次
inline优点:效率,函数特性,类型安全
template<typename T> //由于我们不知道
inline void callWithMax(const T& a, coast T& b) //T是什么,所以采用
{ //pass by reference-to-coast.
f (a>b?a:b);
}
5 总结
1)对于单纯常量,最好以const对象或mums替换#defineso
2)对于形似函数的宏(macros ),最好改用inline函数替换#define