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

宁可以编译器替换预处理器

这个条款获取改为“宁可以编译器替换预处理器”比较好,因为或许 #define不被视为语言的一部分。那正是问题所在。当你做出这样的事情:

#define ASPECT_PATIO 1.653

记号ASPECT_PATIO 也许从未被编译器看见;也许在编译器开始处理源码之前它就被预处理器移走了(#define 的变量单纯被替换)。于是记号名称有可能没进入记号表。当运用此常量但获得一个编译错误信息时,可能会带来困惑,因为这个错误信息也许会提到1.653而不是ASPECT_PATIO
解决之道是以一个常量替换上述的宏:

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

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

两种特殊情况

  1. 定义常量指针
const char * const authorName = "Scotte";
或
const std::string anthorName("Scotte");
  1. class专属常量
    为了将常量的作用域限制于class内,你必须让它成为class的一个成员(member)‘而为确保此常量之多只有一份实体,必须声明为static
class GamePlayer
{
private:
	static const int NumTurns = 5; //常量声明式
	int scores[NumTurns];     //使用该常量
};

若要取专属常量的地址,则还需要在类的实现文件中提供如下定义

const int GamePlayer::NumTurns; //变量的定义,没有初值,因为在上面声明时已经获得初值。

#define不仅不能够用来定义class专属常量,也不能够提供任何封装性。
旧式的编译器不支持上述语法,可以将初值放在定义式

class CostEstimate
{
private:
	static const double FudgeFactor; //声明位于头文件
};

const double CostEstimate::FudgeFactor = 1.35;  //常量定义位于实现文件

还可以使用 "the enum hack"补偿

class GamePlayer
{
private:
	enum{ NumTurns = 5 }; //令NumTurns 成为5的一个记号
	int scores[NumTurns];    
};

宏实现函数

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

使用template inline函数代替

template<typename T>
inline void callWithMax(const T &a, const T &b)
{
	f(a > b ? a : b);
}

请记住

  • 对于单纯常量,最好以const对象或enums替换#defines
  • 对于形似函数的宏,最好改用inline函数替换#defines.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值