尽量以const、enum、inline替换 #define——条款02

        这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许 #define 不能被视为语言的一部分。

一、比如定义一个宏:

#define ASPECT_RATIO 1.653

        这个ASPECT_RATIO也许从未被编译器看见。也许在编译器开始处理源码之前就被预处理器移走了。于是记号名称ASPECT_RATIO有可能没进入记号表内,当你运用此常量但获得一个编译器错误信息时,可能会带来困惑,因为这个错误信息也许会提到1.653而不是ASPECT_RATIO。

    解决方法是用常量来替换宏:

        const double AspectRatio = 1.653

        作为一个语言常量,AspectRatio肯定会被编译器看到,当然就会进入记号表内。此外对浮点常量而言,使用常量可能比使用#define 产生的代码量少,因为预处理器“盲目地将宏名称ASPECT_RATIO替换为1.653”可能导致目标码出现多份1.653,若改用常量AspectRatio绝不会出现相同情况。

二、另外有时候代码用宏来定义一个简单的函数,比如:

    #define RECTANGULAR_AREA(a, b) f(a*b)

    当然上述写法是有问题的,之前在面试题库中就找到过类似的问题,当“a”是一个(2+3)这种形式的值时就会出错。

    正确写法:

    #define RECTANGULAR_AREA(a, b) f((a) * (b))

这里可以写一个inline函数来替换到该宏,就是一个简单的乘法运算。

template<typename T>
inline T rectanglarArea(const T& a, const T& b) {
    return a*b
}

三、#define并不重视作用域。

        一旦宏被定义,它就在其后的编译过程中有效(除非在某处被#undef)。这意味#define不能提供任何封装性,没有所谓的private #define这样的东西。但是const成员变量是可以被封装的。

四、enum替换define场景

class GamePlayer {
private:
    static const int NumTurns = 5  //常量声明式
    int scores[NumTurns];          //使用该常量
    ...
};

        通常C++要求你对所使用的任何东西提供一个定义式,但如果它是个class专属常量又是static且为整数类型,则需特殊处理。只要不取它们的地址,你可以声明并使用它们而无需提供定义式。但如果取某个class专属常量地址或纵使你不取其地址而你的编译器去(不正确地)坚持要看到一个定义式,你就必须另外提供定义式如下:

const int GamePlayer::NumTurns; // NumTurns的定义

        上述这个式子是放在实现文件而非头文件。由于class常量已在声明时获得初值(例如先前声明NumTurns是设置为5),因此定义时不可用再设初值。

        旧式编译器也许不支持上述语法,不允许static成员在其声明式上获得初值。此时可改用所谓的“the enum hack”补偿做法。其理论基础是:“一个属于枚举类型的数值可权充ints被使用”,于是GamePlayer可定义如下:

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

 

请记住

  • 对于单纯常量,最好以const对象或enums替换#defines。

  • 对于形似函数的宏(macros),最好改用inline函数替换#defines。

        关于宏定义,一般从C转C++的开发者来说用用#define的习惯,但是宏定义主要是编译器不会对其进行检查,之后盲目的将对应记号替换成设定的值,这就要求开发者要足够小心,另外出现由#define引起的问题也很难排查,所以在开发过程中尽量避免#define是很好的建议。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值