下面是我对C++中宏的使用的一些看法:
1. 宏这个玩意,如果可以找到代替品(如const variable,inline function,template)的话,就最好别用。
2. 如果没法代替的话,应该按该宏是否会在头文件里使用分成两类:
(1) 在头文件里使用宏是最容易出问题的。因为user在直接或间接的include一个包含宏的头文件时,就也引入了那些宏。由于宏是不受namespace管制的,不管哪个库里过来的宏都堆在一起,很容易发生冲突。所以不到万不得已绝对不要在头文件里加入宏。我目前遇到的需要在头文件(包括inline函数)中使用的宏有:
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#define CHECK(expression) \
if (!(expression)) { \
std::cerr << "CHECK failed at " \
<< __FILE__ << ":" << __LINE__ << "!\n" \
<< "The value of " << #expression << " is " \
<< (expression) << std::endl; \
std::abort(); \
}
#define ABORT(message) { \
std::cerr << "Aborted at " \
<< __FILE__ << ":" << __LINE__ << "!\n" \
<< "Message: " << message << std::endl; \
std::abort(); \
}
(2) 只在源文件里使用的宏危害没有那么大。因为一个源文件中的宏在其他源文件不可见,不会产生污染。需要在多个源文件中使用的宏应该放在一个macros4cc.h里。这种XXX4cc.h文件只允许在源文件里include,而不许在其它头文件里include,而且也不应该提供给用户。
3. 真要用宏的时候,宏的名字应该全部是大写字母,而除了宏以外的其他东西的名字都不要全部大写(Google C++ coding style里规定const variable以小写k开头以保证这一点)。这样宏就算冲突也发生在宏之间。在G++中,当出现同名但是定义不同的宏时,会给出一个warning;如果同名而且定义也相同,那就没事——也确实不会出事。所以宏之间的冲突有编译器看着还安全一点——虽然发现冲突以后处理起来还是很麻烦。