宏在C++中的替代解决方案
来源:互联网 发布:linux系统可以ghost吗 编辑:程序博客网 时间:2024/06/10 18:48
宏在C++中的替代解决方案
宏,在C语言中是个神的存在,能够玩出各种花样,也正因为此,才会给普通程序员造成不少的困扰。由于宏只在预编译阶段起作用,使得编译器无法检测其中的Bug,作为新时代的C++程序员,还是远离的好。
C++为宏提供了一些替代的解决方案,嗯,是一些。
1. 常量定义
#define NUM 100
《EffectiveC++》的第一个条款,讨论的就是这个宏。由于宏是预编译程序来处理,所以NUM这个名字不会加入到符号表中,如果出现编译错误时,提示信息中就不会出现NUM,而是100,为排除错误增加了额外的障碍。
替代方案就是使用const来定义常量,或者使用枚举enum。
const int NUM = 100;
const常量放在头文件中,也不必担心存在多个实例的问题,对于const修饰的变量,编译器一般也会对其进行优化,不会出现多重定义的问题。
C语言中还有一个特殊的常量定义:NULL。其一般的定义为 #define NULL 0,指针的内容却是一个整型,这不符合常理。所以在C++11中使用nullptr代替了NULL。
2.函数定义
由于宏只是在代码中做字符串替代展开,所以,用宏定义的函数,实际上并没有减少代码的体积。另外,还有一些天然的缺陷,假设一个求平方的函数宏
#definesquare(x) (x*x)voidf(double d, int i){square(d); //OKsquare(i++); //糟糕, (i++*i++)square(d+1); //更糟,(d+1*d+1)}
纵然可以把参数加上括号来解决,#define square(x) ((x)*(x)),但i++被执行两次这个问题还是无法解决。
C++中的替代方案,就是使用inline函数。
inline int square(intvalue){ return value*value;}
inline函数具有函数的性质,参数传递不管是传值还是传引用,都不会对参数进行重复计算;同时会对参数做类型检查,保证代码的正确性;inline函数也是在代码中做代码展开,效率上并不比宏逊色。
如果整型不满足需求,还可以定义为模板:
template<classT>inline T square(T& value){ return value*value;}
还有一种更离谱的函数定义形式:
#defineNull_Check(p)\if(p == NULL) return;
这种使用反斜杠定义的函数,更得注意,如果在反斜杠后多了个空格的话,有的编译器会出现变异错误,而提示信息嘛,你可能会困扰很久的。因为反斜杠会对空格这个字符做反义,就会在代码中的引入非法字符,人眼是很难发现这种错误的。
3.类型重定义
#defineDWORD unsigned int
这种类型重定义完全可以使用 typedef unsigned int DWORD 来替代。
4.条件编译
#ifdefSystemAtestA();#else//SystemBtestB();#endif
这种条件编译宏,一般在不同的产品或平台使用同一套代码的情况,大量出现。定义了SystemA的时候,SystemB的代码是不编译的,也就意味着你的代码没有时刻处于编译器的监控中。可以使用template技术来解决。
constint SystemA = 1;constint SystemB = 2; template<int T>void test(){}//定义不同的系统的特化版本template<> void test<SystemA>(){ //SystemA的实现 }template<> void test<SystemB>(){ //SystemB的实现 }
这样,不同的系统使用自己的模板即可,别人的代码也会同时接受编译器的检查,不至于出现遗漏编译错误的情况。
5.头文件包含
#ifndeftest_h#definetest_h //test.h的实现#endif
为了防止头文件重复包含,C++中现在也只能这么做,目前没有别的替代方案。且看看原委,Bjarne Stroustrup在《C++语言的设计与演化》一书中,提供了一个include的设计,可惜的是并没有真正实现。(Cpp, 即C语言预处理器)
我曾经建议可以给C++本身增加一个include指示字,作为Cpp的#include的替代品。C++的这种include可以在下面三个方面与Cpp的#include不同:
1)如果一个文件被include两次,第二个include将被忽略。这解决了一个实际问题,而目前这个问题是通过#define和#ifdef,以非常低效而笨拙的方式处理的。
2)在include的正文之外定义的宏将不在include的正文内部展开。这就提供了一种能够隔离信息的机制,可以使这些信息不受宏的干扰。
3)在include的正文内容定义的宏在include正文之后的正文处理中不展开。这保证了include正文内部的宏不会包含它的编译单位强加上某种顺序依赖性,并一般地防止了由宏引起的奇怪情况。
对于采用预编译头文件的系统而言一般地说,对于那些要用独立部分组合软件的人们而言,这种机制都将是一个福音。请注意,无论如何这还只是一个思想而不是一个语言特征。
也就是说,这个想法在C++中并没有实现。
如果你没有很好的驾驭宏,那就敬而远之吧。
- 宏在C++中的替代解决方案
- 宏在C++中的替代解决方案
- 宏在C++中的替代解决方案
- UITextAlignmentCenter在6.0中的替代
- cellspacing属性在css中的替代方法
- 在iOS5中的UDID替代方案
- mstsc /admin 在linux中的替代命令
- Mysql替代解决方案Cassandra
- 谈谈个人在软件中的不可替代性
- Select.add()在IE中的异常以及替代方法
- java中DataOutputStream.writeUTF(String)在c#中的替代
- gluPerspective and gluLookAt 在OpenGL-ES中的替代
- Java中DataOutputStream.writeUTF(String)在c#中的替代
- JasperReport在Weblogic中的解决方案
- PHP中的替代语法
- Java替代C语言
- 替代链接 extern “C”
- 关于##在C宏定义中的作用
- [android]控件EditText常用属性
- tomcat+花生壳 搭建服务器供外网访问
- 从花瓣与堆糖看Pinterest模式在中国的可行性
- 企业如何软件商业化? .
- 关于android流量统计
- 宏在C++中的替代解决方案
- Methods To Speed Up Magento - A Guide To Making Magento Faster
- HDU 1158 雇佣决策 动态规划,只要肯用空间,时间,这题就是简单题
- 尺度空间
- PHP模块开发(一) PHP环境搭建
- [android]控件Button常用属性
- Box2D C++教程6-定制器(Fixtures)
- 推荐免费WEB打印控件PAZU
- C基础printf、scanf函数、,号运算符