前言

  在面向过程语言,如 C 语言中,#define 非常常见,也确实好用,值得提倡。但在如今面向对象的语言,如 C++ 语言中,#define 就要尽量少用了。

  为何在 C++ 中就要少用了呢?

  这是因为 #define 机制只是简单的字符替换,这样一方面你无法对 #define 定义的东西加入一些C++语法元素,因此限制了面向对象编程语言的威力;

  另一方面编译器不能获取到你所定义的变量类型/函数类型,因此无法提供全面的检测机制,导致隐藏 bug 增多。

  所以要想出对 #define 机制进行替代的思路。

思路一:使用类变量代替宏全局变量

  步骤:

    1. 在类定义式内声明 static 成员

    2. 在类的实现文件内初始化该成员

    3. 由该类派生出的任何对象都可以访问这个成员。

  示例代码:

 #include <iostream>

 using namespace std;

 class CA
{
public:
static const float a;
}; const float CA::a = 5.0; int main ()
{
cout << CA::a << endl; cin.get(); return ;
}

思路二:类定义中就要用到的全局常量使用 enum 实现

  在思路一中,如果类 CA 要使用到 a,比如类中要声明一个数组,则下面语句是非法的:int arrayA[a];。为啥?因为在类定义的头文件中,编译器还获取不到 a 的具体值。因此,可以采用所谓的 the enum hack 做法来解决这个问题。

 enum { ArrayNum= };
int array[ArrayNum];

思路三:采用 template inline 函数代替宏函数

  预处理器的一个很重要的功能是实现宏函数,如下面这个宏函数能够返回 a 和 b 之间较大的值而不论a 和 b的具体类型:

 #define CALL_WITH_MAX(a, b) f((a)>(b)?(a):(b))

  但这样的实现有好几个漏洞,读者不放试着自己找出来。

  而采用 template inline 函数不单没有这些漏洞,还可以给它添加各种语法机制,比如将它定义为某个类的成员函数。下面的代码演示了 template inline 函数实现改功能的具体做法:

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

小结

  这三个思路在很多时候都可以替换掉 #define。

  然而,#define 并没有彻底退出舞台,它提供的条件编译功能目前也是非常实用的。

尽量多的以 const/enum/inline 替代 #define的更多相关文章

  1. 第一篇:尽量多的以 const/enum/inline 替代 #define

    前言 在面向过程语言,如 C 语言中,#define 非常常见,也确实好用,值得提倡.但在如今面向对象的语言,如 C++ 语言中,#define 就要尽量少用了. 为何在 C++ 中就要少用了呢? 这 ...

  2. Book. Effective C++ item2-尽量使用const, enum, inline替换#define

    ##常规变量 c++里面的#define后面的定义部分,是不算代码的一部分的.所以如果你使用#define: #define ASPECT_RATIO 1.653 你希望这个代号ASPECT RATI ...

  3. 读书笔记_Effective_C++_条款二:尽量以const, enum, inline替换#define

    其实这个条款分成两部分介绍会比较好,第一部分是用const和enum替换不带参的宏,第二部分是用inline替换带参的宏. 第一部分:用const和enum替换不带参宏 宏定义#define发生在预编 ...

  4. NO.2: 尽量以const,enum,inline 替换 #define

    1.首先#define 定义不重视作用域(scope),虽然可以#undef控制,但是不美观,还存在多次替换的问题,以及没有任何封装性. 2.const XXX_XX,保证其常量性以及可控的作用域,如 ...

  5. Effective C++阅读笔记_条款2:尽量以const,enum,inline替换#define

    1.#define缺点1 #define NUM 1.2 记号NUM可能没有进入记号表,在调试或者错误信息中,无法知道1.2的含义. 改善:通过const int NUM = 1.2; 2.#dein ...

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

    class GamePlayer{private: static const int NumTurns = 5; int scores[NumTurns]; ...}; 万一你的编译器(错误地)不允许 ...

  7. Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define

    尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...

  8. 条款2:尽量以const, enum, inline替换#define

    原因: 1. 追踪困难,由于在编译期已经替换,在记号表中没有. 2. 由于编译期多处替换,可能导致目标代码体积稍大. 3. define没有作用域,如在类中定义一个常量不行. 做法: 可以用const ...

  9. 尽量用const,enum,inline代替define

    在读<Effective C++>之前,我确实不知道const,enum,inline会和define扯上什么关系,看完感觉收获很大,记录之. define: 宏定义. 在编译预处理时,对 ...

随机推荐

  1. spring mvc如何获取问号后的url参数

    @RequestMapping(method=RequestMethod.GET) public ModelAndView allUsers(@RequestParam int page){ Mode ...

  2. thinking in java之Collections工具类的使用

    代码摘自<thinking in java>4td 此实例非常好的总结了Collections的一些常见方法的使用. package countainers; import java.ut ...

  3. js基础之COOKIE

    一.COOKIE的封装函数 function setCookie(name,value,eDate){ var oDate = new Date(); oDate.setDate(oDate.getD ...

  4. IBatis.net 输出SQL语句(七)

    一.IBatis.net输出SQL语句到控制台 输出IBatis.net生成的SQL语句到控制台,能够方便调试. 如果要想输出IBatis.net的SQL语句到控制台,那么只需要做如下配置即可: &l ...

  5. 腾讯微博数据抓取(java实现)

    不多说,同样贴出相关代码 参数实体: package token.def; import java.io.Serializable; import java.util.Properties; publ ...

  6. Android Studio 配置JPush

    1.在JPush官方下载 JPush SDK(jpush-android-arm-2.1.0.zip),我下载的是2.1.0: 2.解压下载好的压缩包(jpush-android-arm-2.1.0. ...

  7. c#读取文本文档实践2-计算商品价格

    商品 数量 单价英语 66 100语文 66 80数学 66 100化学 66 40物理 66 60 上面是文本文档中读入的数据. using System; using System.Collect ...

  8. 番茄工作法和Bullet Journal笔记法

    番茄工作法是一套时间管理方法,Bullet journal是一套笔记记录的方法,最近通过学习这2个方法来管理自己的时间,让自己战胜拖延症. 番茄工作法 番茄工作法的整体思路就是将时间分割成一个个小时间 ...

  9. 学习js之类的使用

    <script language="javascript">function Person(){    }Person.prototype={    name:null ...

  10. ACM - 概率、期望题目 小结(临时)

    概率DP求期望大多数都是全期望公式的运用.主要思考状态空间的划分以及状态事件发生的概率.问题可以分为无环和有环两类.无环一类多数比较简单,可以通过迭代或者记忆化搜索完成.有环一类略复杂,可以通过假设方 ...