条款02:尽量以const, enum, inline替换 #define

尽量以const, enum, inline替换 #define


const

在我们所编写的代码中经常会出现以下预处理命令

#define ASPECT_RATIO 1.653

注意:但是这并不是一个好的做法,因为很可能在编译器处理源代码之前,它就被(#undef)了这样就会造成符号名称ASPECT_RATIO没有进入符号表(symbol table)。

比如很可能在源代码文件的某一处会出现以下预处理命令

#undef ASPECT_RATIO



比较好的做法是以一个常量替换上述的宏,代码如下。

const double AspectRatio = 1.653
  • 此时的AspectRatio是属于源代码的一部分因此一定可以被编译器发现
  • 也更方便我们去追踪
  • 另一个优点是可以生成更小的码。比如,当我们使用#define方法时,编译器可能只是简单将ASPECT_RATIO替换成1.653这样可能就会造成更多的目标码(object code)

enum

对于class的专属常量。我们既会声明它为const同时也会声明它为static
比如很可能有如下代码。

class GamePlayer{
private:
    static const int NumTurns = 5; // 声明常量NumTurns(不是定义式)
    int  scores[NumTurns];         // 使用常量NumTurns
    ...
};

注意:然而这么做在某些情况下依然会发生问题,比如有些编译器会强制要求你在使用一个变量之前定义它。不然便会编译报错。



定义static变量代码如下

const int GamePlayer::NumTurns;     // 之所以没有赋初值是因为static在声明时就
                                    // 已经初始化了

注意:可这样做的话,依然会有问题有些编译器不支持在声明式中赋初始值,于是你可能会有如下做法。

class GostEstimate{
private:
    static const double FudgeFactor; // static class常量声明
                                     // 位于.h文件内
    ...
};
const double                         // static class常量定义
    CostEstimate::FudgeFactor = 1.35;// 位于.cpp文件内

注意:间接引入了一个新问题,前面的GamePlayer的数组坚持要在编译时间知道数组的大小。如果编译器报出“不允许static 整数型class常量完成 in class 初值设定”,则可使用enum hack的做法



enum hack代码做法如下

class GamePlayer{
private:
    enum{ NumTurns = 5};
    int scores[NumTurns];
};

inline

对于max, min我们经常会用一个宏去定义。比如

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))

注意:这里尽管用括号将宏参数括起来了,但是依然避免不了调用出错。比如会有如下代码

int a = 0, b = 0;
max(++a, b);        // a被累加2次
max(++a, b+10);     // a被累加1次



以下是用inline做法

template<typename T>
inline T max(const T& a, const T& b)
{
    return a > b ? a : b;
}
  • 这里这样做的好处
    • 不需要在函数本体中为参数加上括号
    • 不需要操心参数被运算多次
    • max是个函数遵守作用域(scope)和 访问规则

你可能感兴趣的:(读书笔记-Effective,C++)