可以改为“宁可以编译器替换预处理器”
#define ASPECT_RATIO 1.653
ASPECT_RATIO也许从来未被编译器看见,也许在编译器开始处理源码之前就被预处理器移走了。因此,可能没进入记号表(symbol table)内。在运用此常量但获得一个 编译错误信息时,提示1.653而不是ASPECT_RATIO,这就带来一些困惑。
解决方案:
const double AspectRatio = 1.653;
语言常量肯定会被编译器看到,会进入记号表内。可能比使用宏定义导致较小量的代码,因为预处理器“盲目地将宏名称ASPECT_RATIO替换为1.653”导致目标码多出一份1.653。
常量替换宏定义的场景:
- 定义常量指针:长定义于头文件,一般声明为char*-based字符串
const char* const authorName = "Jane";
const std::string authorName("Jane");//更适合字符串常量
- class专属常量:将常量作用域限制在class内部,使它成为class的一个成员(为使得始终只有一份,还需声明为static)
class GamePlayer{
static const int NumTurns = 5;
int scores[NumTurns];
};
注:旧式编译器不允许static成员在声明时获得初值。此外所谓的“in-class初值设定”也只允许对整数常量进行。须放在实现文件内。这时可以改用enum-hack补偿做法。
class GamePlayer {
private:
enum { NumTurns = 5}; // the enum hack
int scores[NumTurns];
};
#define实现宏看起来不会招致函数调用带来的额外开销:
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
取而代之的是template inline,它可以获得宏带来的效率以及一般函数的所有可预料行为和类型安全性。
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
template产出一整群函数,每个函数都接受两个同型对象,并以其中较大者调用f。callWithMax是一个真正的函数,遵守作用域和访问规则。
总结:
- 对于单纯常量,最好以const对象或enums替换#define
- 对于形似函数的宏,最好改用inline函数替换#defines