问题:
我用基本的C++配合STL写了一个库,编译成静态库lib。
又在同一个工作空间里面建立了个win32 console的工程,调用这个lib,一切正常。然后我想加个界面,又建立了个基于对话框的mfc工程,用一样的方法include静态库工程的头文件,居然说我原来那个工程的文件语法有错,而且报的很奇怪,例如:
1
2
3
4
5
6
7
8
9
10
|
#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 MYXXXX
int 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
转载请注明出处