宏定义污染的解决方法。
来源:互联网 发布:淘宝首页模板免费下载 编辑:程序博客网 时间:2024/05/21 15:49
问题:
我用基本的C++配合STL写了一个库,编译成静态库lib。
又在同一个工作空间里面建立了个win32 console的工程,调用这个lib,一切正常。然后我想加个界面,又建立了个基于对话框的mfc工程,用一样的方法include静态库工程的头文件,居然说我原来那个工程的文件语法有错,而且报的很奇怪,例如:
#include ...
class
Operation
{
public
:
enum
kind_t{NONE=0,ADD,DELETE,REVERSE};
kind_t kind;
Node::pointer_t from,to;
public
:
...
};
它说我enum的那一行在“)”前面缺少“}”。
2>d:\my program\projects\bayesian\bayesian\operation.h(12) : error C2143: 语法错误 : 缺少“}”(在“(”的前面)
2>d:\my program\projects\bayesian\bayesian\operation.h(12) : error C2059: 语法错误 : “<L_TYPE_raw>”
2>d:\my program\projects\bayesian\bayesian\operation.h(12) : error C2143: 语法错误 : 缺少“;”(在“}”的前面)
2>d:\my program\projects\bayesian\bayesian\operation.h(12) : error C2238: 意外的标记位于“;”之前
原因:
一开始怀疑是头文件顺序的问题,后来发现不是。
经过反复测试后发现,这其实是windows.h中的宏定义污染导致的。
在windows.h间接导入的WinNT.h中宏定义了“DELETE”为一个整数。
单独编译那个lib工程以及那个使用基本C++的win32 console工程,由于没有导入windows.h,所以编译他们的时候一切正常。但是在MFC工程里面,由于在这个导入是根植于mfc框架中的,无法避免,所以导致了宏定义污染。宏定义在预编译阶段覆盖掉了我的有效标示符,导致莫名其的错误。
相同的问题还出现在STL的max,min一些函数上。
解决:
0,适用#undef xxx来取消xxx的宏定义。
此方法过于暴力,只适用简单情况,对于复杂情况,你undef掉的东西在编译其他库文件的时候是必须的,会导致编译错误。
温和方法:
根本思路是让与编译器认为你的标示符是不同于宏定义中标示符的。
1,最基本的方法就是给自己定义的标示符换个名字,加个前缀。
这样最简单有效,但是不适用于STL组件。
2,名字包装,用括号包裹函数名(定义和调用都要)。
原理是让预编译器看到标示符与“(”之间还有一个“)”,破坏了结构。
特点就是简单。这种方法只适用于带参数的宏定义,即基本只能保护函数,无法保护变量(常量)。但它无法保护成员函数。
因为obj.do()如果写成obj.(do)()是不合语法的。
例如:
#define max(a,b) ((a)>(b)?(a):(b))int (max)() { return 999; } // 用圆括号包装test, 编译器看到 "test)(...)" ,与 "test(...)" 是不一样的符号.这里这个例子从语义上不太恰当,只用来说明意思。
3,用其他宏间隔开,自己定义一个空的宏。放在函数名与括号之间(和函数名之间要有空格:-))。
这种方法稍微复杂一点。同样只能保护函数,不能保护变量(常量)。但是它可以保护成员函数,和作用域标示符中的函数。
因为在C++中函数名和函数参数列表之间可以有任意多个间隔符。
例如:
#define cal(x) (15+x)#define MYXXXXint cal MYXXX (int x){ return x;}...int x=cal MYXXX (1);//调用自己的版本int x=cal(1);//调用宏定义的版本
下面是一个完整的例子:
转载要有素质,这个例子来自:http://blog.chinaunix.net/uid-22283027-id-3393561.html
一个完整的测试样例 < vc2005验证通过 >#define test(A,B) ( "call macro test" )#define BOOST_PREVENT_MACRO_SUBSTITUTION// #include <C:\boost_1_45_0\boost/cstdint.hpp>char* (test)(int a, int b){ return "call function test"; }namespace ns{ char* test BOOST_PREVENT_MACRO_SUBSTITUTION(int a,int b) { return "call function ns::test"; }}int main ( int, char ** ){ cout << test (1,2) << endl; // call macro test cout << (test)(1,2) << endl; // call function test cout << (ns::test)(1,2) << endl; // call function ns::test cout << test BOOST_PREVENT_MACRO_SUBSTITUTION(1,2) << endl; // call function test cout << ns::test BOOST_PREVENT_MACRO_SUBSTITUTION(1,2) << endl; // call function ns::test return 0;}
原载于http://blog.csdn.net/yanxiangtianji
转载请注明出处
- 宏定义污染的解决方法。
- 解决C++中宏定义导致的名字污染
- “AF_IPX”: 宏重定义的解决方法
- 被污染的药瓶
- cookie的污染!
- 室内环境污染的表现
- 被污染的药丸
- Javascript 定义命名空间,减少全局变量污染
- 闹心的飞机噪音污染!!
- 避免全局变量污染的解决办法
- 简单定义js类并调用,防止全局污染
- VS中重复定义的解决方法
- 类型重定义冲突的解决方法
- 类型重定义的一个解决方法
- C++类型重定义错误的解决方法
- 模板函数定义迭代器不识别的解决方法
- 可叹,环境的污染(七律一首)........
- 让Firefox的DNS不被污染
- xCode 4.3版本的语法高亮和提示BUG
- 使用MyEclipse创建JSP页面的一般步骤
- Mac系统下的远程登录设置
- 第四次上机实验
- 关于TabHost显示两行或多行的问题
- 宏定义污染的解决方法。
- 解决getOutputStream() has already been called for this response
- 安卓-理论知识之AsyncTask
- 反馈行为与设计动态流程引擎的一些思考
- 感谢CSDN编辑精心采访--将人文融入到科技产品中
- http错误代码
- ForEach 语法
- mysql常用监控脚本命令列表
- 批量编辑修改表中某一字段