《Effective C++》学习笔记 02

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

实际是:应该让编译器代替预处理器定义,因为预处理器定义的变量并没有进入到symbol table里面。编译器有时候会看不到预处理器定义

所以用

const double Ratio = 1.653;

来代替

#define Ratio 1.653

当我们以常量替换#defines,有两种特殊情况需要注意。

第一是定义常量指针( constant pointers )

由于常量定义式通常被放在头文件内(以便被不同的源码含入),因此有必要将指针(而不只是指针所指之物)声明为const。

const char* const authorName = "Scott Meyers";

第二个值得注意的是class专属常量。

为了将常量的作用域(scope)限制于class内,你必须让它成为class的一个成员(member );而为确保此常量至多只有一份实体,你必须让它成为一个static成员:

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

另外提供定义式如下:

const int GamePlayer::NumTurns;  //NumTurns的定义;
                                  //由于声名式给予了数值,这里就不用了

我们把这个式子放进一个实现文件而非头文件。

如果编译器不支持在class内对static成员在声明式上获得初值,我们可以将初值放在定义式:

class CostEstimate{
private:
    static const double FudgeFactor;    //static class常量声明
                                         //位于头文件内
};
const double                                            //static class常量定义
     CostEstimate::FudgeFactor = 1.35;                  //位于实现文件内

但这样也有例外当我们在class编译期间需要一个class常量值,例如在上述的GamePlayer::scores的数组声明式中(是的,编译器坚持必须在编译期间知道数组的大小)。这个时候可以改用所谓的"the enum hack"补偿做法。其理论基础是:“一个属于枚举类型(enumerated type)的数值可权充ints被使用

class GamePlayer{
private:
    enum{NumTurns=5};                           //"the enum hack',一令NumTurns
                                                //成为5的一个记号名称.
    int scores[NumTurns];                       //这就没问题了.
    ...
};

注:取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法。

另一个常见的#define误用情况是以它实现宏(macros ) 。宏看起来像函数,但不会招致函数调用(function call)带来的额外开销。下面这个宏夹带着宏实参,调用函数f:

//以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被累加一次

在这里,调用f之前,a的递增次数竟然取决于“它被拿来和谁比较”!

template inline函数可以解决这个问题

template<typename T>                                 //由于我们不知道
inline void callWithMax(const T& a, coast T& b)      //T是什么,所以采用
{                                                    //pass by reference-to-coast.
    f (a>b?a:b);                                     //pass by reference-to-coast.
}                                                    //见条款20.

总结:
1:对于单纯常量,最好以const对象或mums替换#defines。
2:对于形似函数的宏(macros ),最好改用inline函数替换#defines。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值