Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5760860
  • 博文数量: 291
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 7924
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-06 14:28
个人简介

阿里巴巴是个快乐的青年

文章分类

全部博文(291)

文章存档

2018年(21)

2017年(4)

2016年(5)

2015年(17)

2014年(68)

2013年(174)

2012年(2)

分类: C/C++

2013-06-30 10:11:31

        这个条款其实就是宁可以编译器替换预处理器,因为#define不被视为语言的一部分,比如:
        #define ASPECT_RATIO 1.653
        在编译器处理源码前,ASPECT_RATIO就被预处理器替代成1.653了,因此,ASPECT_RATIO有可能没进入symbol table内,那么当编译或调试时,如果出现错误而ASPECT_RATIO又非你所在的头文件内,则你会对1.653是什么感到莫宁其妙而浪费跟踪时间。
一、const替代#define
        解决上面问题的方法是以常量替换上述的宏:
        const double AspectRatio = 1.653;
        作为语言常量,AspectRatio肯定会被编译器看到,并进入symbol table内。
        为了将常量作用于限制于class内,你必须让它成为class的一个成员即class专属常量,而为确保此常量至多只有一份实体,你必须让它成为一个static成员:
        class GamePlayer{
        private:
                static const int NumTurns = 5;    //常量声明式
                int scores[NumTurns];                //使用该常量
                ...
        };
        需要注意的是:#define不重视作用于域,一旦宏被定义,则在其后整个编译过程中都有效,除非在某处被#undef了,这意味着#define不能用于定义class专属常量,也不能提供任何封装性,即private #define之类的东西。
        如果编译器不支持前面这种声明方式,则你需要如下定义:
        class CostEstimate{
        private:
                static const double FudgeFactor;        //static class常量声明位于.h头文件内
                ...                        
        };
        const double CostEstimate::FudgeFactor = 1.35    //static class常量定义位于.cpp源文件内
        当然这不适合用于前面GamePlayer::scores的数组声明式,因为编译器在编译期间需要知道数组大小即需要一个class常量值。
        如果编译器不支持而你又有这种声明数组的需求,则可用“the enum hack”补偿做法来实现。

二、const替代#define        
        如下来重新定义GamePlayer:
        class GamePlayer{
        private:
                enum {NumTurns = 5};        //"the enum hack"
                int scores[NumTurns];
                ...
        };

三、inline替代#define        
        为了减少函数调用开销我们通常用宏来代替函数,但是宏夹带着实参时,参数必须加上小括号,否则后果很严重,但是即便如此还是会有问题,比如:
        #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                     //因为类型不确定
        inline void CallWithMax(const T &a, const T &b)    //T可能是有比较操作符的对象,因此,用引用
        {
                f (a > b ? a : b);
        }
        需要注意的是:对于单纯常量,最好以const对象或enums替换#define;对于形似函数的宏,最好用inline替换#define。




阅读(8561) | 评论(9) | 转发(3) |
给主人留下些什么吧!~~

scq2099yt2013-09-28 15:21:18

kdkgod:在effective c++书中第一条就是这个,刚开始不是很理解,工作三年现在才有点体会。单单define宏就出现过两次问题,一次是自己define两次,当时也没有关注warning,查了很久才发现,另一次是和同事冲突。唉,define 能不用就不用吧。

很多东西都是随着经验增长有新的认识的

回复 | 举报

kdkgod2013-09-28 09:57:39

在effective c++书中第一条就是这个,刚开始不是很理解,工作三年现在才有点体会。单单define宏就出现过两次问题,一次是自己define两次,当时也没有关注warning,查了很久才发现,另一次是和同事冲突。唉,define 能不用就不用吧。

scq2099yt2013-07-01 13:32:43

学而不思则罔:搞懂了每一个的特性,和应用环境,择优使用吧。

文明上网,理性发言...

回复 | 举报

学而不思则罔2013-07-01 11:29:32

搞懂了每一个的特性,和应用环境,择优使用吧。