造成严重错误。比如:#include#includeusingnamespacestd;#define A 10voidfunc1(){#define A 20cout <<“func1 A =”<< A << endl;}voidfunc2(){ cout <<“func2 A =”<< A << endl;}intmain(){cout <<“main A =”<< A << endl; func1(); func2();return;}输入结论:main A =20func1 A =20func2 A =20从上两个范例他们能窥见,输入结论Accous20。虽然#define只做字面的代替,且全局有效率,因而无论表述在这儿单厢在后处置的这时候全数代替掉,因而增添的效用是表述的函数虽说在自上而下均可出访。上范例中,在func1中再次表述了函数A,引致前面大部份的A都变为了20。他们何不将func1的实现放到main函数后,看一看有甚么结论,如下表所示例右图:#include#includeusingnamespacestd;#define A 10voidfunc1();voidfunc2(){ cout <<“func2 A =”<< A << endl;}intmain(){cout <<“main A =”<< A << endl; func1(); func2();return;}voidfunc1(){#define A 20cout <<“func1 A =”<< A << endl;}输入结论:main A =10func1 A =20func2 A =10从那个范例他们能窥见,在C++的后处置期,#define的确是依照次序来自上而下展开代替,如上所述表述A的值为10,因而main函数中的A和func2中的A均被代替为10,而最终在处置到func1的函数体的这时候,A再次被表述为20,因此func1中的A被代替为20。虽然宏表述只做代替,因此没中文名称的基本概念,所以宏在C++后处置的这时候就被代替了,因而在标识符增容操作过程中更不难辨认出难题。比如此例中,在预校对期A全数被代替为位数10因而,在C++中他们尽量避免采用#define来表述两个自函数,应采用const和enum来表述自函数。尽量避免形如函数的宏#define的除此之外两个须要特别注意的地方性是,尽量避免形如函数宏的采用。比如下表所示面的范例:#include#includeusingnamespacestd;#define T a + a#define TT T – T#define MAXF(a, b) func(a > b ? a : b)voidfunc(int m){ cout <<“func1= “<< m << endl;}intmain(){int a =1;cout <<“a =”<< a << endl;cout <<“T =”<< T << endl;cout <<“TT =”<< TT << endl;int b =; MAXF(++a, b);// a被加总2次 MAXF(a++, b);// a被累加2次 MAXF(++a, b +20);// a被加总1次cout <<“a =”<< a << endl;return;}输入结论:a =1T =2TT =2func1= 3func1= 4func1= 20a =6输入结论可能将与他们的市场预期存有进出,比如他们可能将会指出TT的输入如果为,MAXF的输入可能将与市场预期的不太完全一致。事实上,在此例中预校对期,把大部份的宏代替为适当的函数。当中:对T代替为a+a,T的输入结论为2,TT代替为a+a-a+a,TT的输入结论也为2。对MAXF(++a, b);,首先被代替为func(++a > b ?++a : b);,虽然++a是先递增再比较,2比大,因而func的参数应为++a,a加总了两次,因而MAXF(++a, b);输入的结论为3。对MAXF(a++, b);,首先被代替为func(a++> b ? a++: b);,虽然a++在这里是先比较再递增,3比大,因而func的参数为a++,这这时候a应先将值传递给func,然后再加总,因而func打出来的结论为4。事实上此时a的值已经变为5。对MAXF(++a, b +20);,a在比较大小的这时候加总了一次,6没20大,因而传入func的参数是20,因而打印输入结论为20。最终a总共加总了5次,最终结论为6。采用形如函数的宏有这时候的确会给他们增添方便,但有这时候在直观上也会增添采用上的歧义,事实上也不是宏的错,大部分情况是他们把情况简单化、直观化了,事实上如果将其展开并代替后,他们也能及时辨认出难题,但难题是依照宏的逻辑再次展开分析,已经把他们的工作变得更复杂了,背离了当初他们简单化的初衷。那他们如何防止这些意外的发生呢?对一些简单的宏函数,他们能通过添加括号等方法,强化他们的逻辑,避免不必要的歧义发生,对形如函数的宏,尽量采用inline函数来代替上面的宏表述,具体的同时实现如下表所示右图:#include#includeusingnamespacestd;#define T a + a#define TT (T)- (T)template voidfunc(F m){cout <<“func1= “<< m << endl;}template inlinevoidMAXF(F a, F b){ func(a > b ? a : b);}intmain(){int a =1;cout <<“a =”<< a << endl;cout <<“T =”<< T << endl;cout <<“TT =”<< TT << endl;int b =; MAXF(++a, b); MAXF(a++, b); MAXF(++a, b +20);cout <<“a =”<< a << endl;return;}输入结论:a =1T =2TT =0func1= 2func1= 2func1= 20a =4采用inline函数替代形如函数的宏,使得标识符更加易用,同时也同时实现了类似define的效用。同时,因为他们采用了函数,因而也遵守了作用域和出访的规则,使得他们的标识符更具标准性和规则性。总结在C++中,尽量避免#define自函数和形如函数宏的采用。对一些简单的函数的宏,要避免宏嵌套宏,尽量做到简单,对嵌套宏要做好运算符优先级检查和每一层的嵌套隔离,避免歧义的造成。引用《Effective C++》中的话来做总结是:对单纯自函数,最好以const对象和enum代替#define。对形如函数的宏,最好改用inline函数代替#define。