在使用常量时,上面的两个答案都是正确的,但是#define 不限于单独使用。另一个使用#define 的例子是宏。
宏
宏是预处理器使用的代码片段,它们的工作方式与其他 #define 声明在这方面完全一样。预处理器将用宏的代码从字面上交换您定义的符号的出现。一个例子:
#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)
int main(int argc, char** argv)
{
HELLO_MAC;
}
这实际上会用我声明的代码替换HELLO_MAC 符号。如果它是一个常数,它会做同样的事情。因此,您可以将常量的#defines 视为一种特殊的宏。
您还可以使用宏传递参数,我发现它对于在代码上执行日志记录/异常策略特别有用。
例如
#define THROW_EXCEPT( ex_type, ex_msg ) /
do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)
...
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );
该代码允许我确保每个人都使用引发异常的文件行进行记录。
模板通常是比宏更好的选择,但我不能在这个示例中使用模板函数,因为我需要从 throw 的位置使用 __LINE__ 和 __FILE__ 函数,而不是从模板的位置功能。
哪些地方不应该使用宏?你可以在任何地方使用其他东西。像任何#define 一样,宏都经过预处理,因此编译器根本看不到它们。这意味着永远不会为HELLO_MAC 或THROW_EXCEPT 创建任何符号,因此在调试器中看不到它们。如果您遇到编译错误,它们也可能会令人困惑,尤其是当它们是长宏时。