尽量多的以 const/enum/inline 替代 #define
前言
在面向过程语言,如 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的更多相关文章
- 第一篇:尽量多的以 const/enum/inline 替代 #define
前言 在面向过程语言,如 C 语言中,#define 非常常见,也确实好用,值得提倡.但在如今面向对象的语言,如 C++ 语言中,#define 就要尽量少用了. 为何在 C++ 中就要少用了呢? 这 ...
- Book. Effective C++ item2-尽量使用const, enum, inline替换#define
##常规变量 c++里面的#define后面的定义部分,是不算代码的一部分的.所以如果你使用#define: #define ASPECT_RATIO 1.653 你希望这个代号ASPECT RATI ...
- 读书笔记_Effective_C++_条款二:尽量以const, enum, inline替换#define
其实这个条款分成两部分介绍会比较好,第一部分是用const和enum替换不带参的宏,第二部分是用inline替换带参的宏. 第一部分:用const和enum替换不带参宏 宏定义#define发生在预编 ...
- NO.2: 尽量以const,enum,inline 替换 #define
1.首先#define 定义不重视作用域(scope),虽然可以#undef控制,但是不美观,还存在多次替换的问题,以及没有任何封装性. 2.const XXX_XX,保证其常量性以及可控的作用域,如 ...
- Effective C++阅读笔记_条款2:尽量以const,enum,inline替换#define
1.#define缺点1 #define NUM 1.2 记号NUM可能没有进入记号表,在调试或者错误信息中,无法知道1.2的含义. 改善:通过const int NUM = 1.2; 2.#dein ...
- Effective C++ -----条款02:尽量以const, enum, inline替换 #define
class GamePlayer{private: static const int NumTurns = 5; int scores[NumTurns]; ...}; 万一你的编译器(错误地)不允许 ...
- Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define
尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...
- 条款2:尽量以const, enum, inline替换#define
原因: 1. 追踪困难,由于在编译期已经替换,在记号表中没有. 2. 由于编译期多处替换,可能导致目标代码体积稍大. 3. define没有作用域,如在类中定义一个常量不行. 做法: 可以用const ...
- 尽量用const,enum,inline代替define
在读<Effective C++>之前,我确实不知道const,enum,inline会和define扯上什么关系,看完感觉收获很大,记录之. define: 宏定义. 在编译预处理时,对 ...
随机推荐
- spring mvc如何获取问号后的url参数
@RequestMapping(method=RequestMethod.GET) public ModelAndView allUsers(@RequestParam int page){ Mode ...
- thinking in java之Collections工具类的使用
代码摘自<thinking in java>4td 此实例非常好的总结了Collections的一些常见方法的使用. package countainers; import java.ut ...
- js基础之COOKIE
一.COOKIE的封装函数 function setCookie(name,value,eDate){ var oDate = new Date(); oDate.setDate(oDate.getD ...
- IBatis.net 输出SQL语句(七)
一.IBatis.net输出SQL语句到控制台 输出IBatis.net生成的SQL语句到控制台,能够方便调试. 如果要想输出IBatis.net的SQL语句到控制台,那么只需要做如下配置即可: &l ...
- 腾讯微博数据抓取(java实现)
不多说,同样贴出相关代码 参数实体: package token.def; import java.io.Serializable; import java.util.Properties; publ ...
- Android Studio 配置JPush
1.在JPush官方下载 JPush SDK(jpush-android-arm-2.1.0.zip),我下载的是2.1.0: 2.解压下载好的压缩包(jpush-android-arm-2.1.0. ...
- c#读取文本文档实践2-计算商品价格
商品 数量 单价英语 66 100语文 66 80数学 66 100化学 66 40物理 66 60 上面是文本文档中读入的数据. using System; using System.Collect ...
- 番茄工作法和Bullet Journal笔记法
番茄工作法是一套时间管理方法,Bullet journal是一套笔记记录的方法,最近通过学习这2个方法来管理自己的时间,让自己战胜拖延症. 番茄工作法 番茄工作法的整体思路就是将时间分割成一个个小时间 ...
- 学习js之类的使用
<script language="javascript">function Person(){ }Person.prototype={ name:null ...
- ACM - 概率、期望题目 小结(临时)
概率DP求期望大多数都是全期望公式的运用.主要思考状态空间的划分以及状态事件发生的概率.问题可以分为无环和有环两类.无环一类多数比较简单,可以通过迭代或者记忆化搜索完成.有环一类略复杂,可以通过假设方 ...