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

1.前言

        看到文章的名称,可能会觉得内容更改为宁可以编译器替换预处理器更好,因为#define不被当作语言的一部分,这正是它的问题所在。当写出以下代码:

#define ASPECT_RATIO 1.653

        在上面代码中,记号名称ASPECT_RATIO也许从未被编译器看见(关于编译器和预处理之间的关系,见关于预处理器,编译器,汇编器,连接器的介绍与区别-CSDN博客)也许在编译器开始处理源码之前该名称就被预处理器转移走了。导致记号名称ASPECT_RATIO有可能没进入记号表内。于是在运用此常量但获得一个编译错误信息时,可能会带来困惑,因为这个错误信息会提到1.653,而不是ASPECT_RATIO。于是就会出现这样一种情况:如果ASPECT_RATIO被定义在一个非你所写的头文件内,你肯定对1.653以及它来自何处毫无概念,于是就会导致排错而浪费大量时间。

2.解决方法

        解决问题的方法有很多,一个是以一个常量替换上述的宏(#define):

const double AspectRatio=1.653;//大写名称通常用于宏,因此这里改变名称的写法。

        在这里,作为一个语言常量,AspectRatio肯定会被编译器看到,当然就会进入记号表内。

        当我们以常量替换#define,有两种特殊情况值的说说。第一是定义常量指针(const pointers),由于常量定义式通常被放在头文件内(方便被不同的源码含入),因此有必要将指针声明为const。例如若要在头文件内定义一个常量char-based字符串,必须写const两次:

const char* const authorName="Scott Meyers";

        关于const的意义和使用,string对象一般比其前辈char*-base更好,所以上述的authorName往往定义成这样更好:

const std::string authorName("Scott Meyers");

        第二点 需要注意的是class专属常量。为了将常量的作用域限制于class内,必须让它成为class的一个成员(member);而为确保此常量至多只有一份实体,必须让它成为一个static成员:

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

};

        在该代码段中,NumTurns是声明式而非定义式。通常C++要求对所使用的任何东西提供一个定义式,但如果它是class专属常量,又是static且为整数类型,则需特殊处理。如以下:

class CostEstimate{

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

3.inline的运用

        把焦点拉回预处理器。另一个常见的#define误用情况是以它实现宏(macros),宏看起来像函数,但不会导致函数调用带来的额外开销。例如下面的例子:下面这个宏夹带着宏实参,调用函数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,const T& b)
{
    f(a>b?a:b);
}

        此处callWithMax是个真正的函数,它遵守作用域(scope)和访问规则。比如可以写出“class内的private inline函数”。一般而言宏不能完成此事。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值