假设我们将忽略诸如头卫之类的明显事物。
有时,您想要生成需要由预编译器复制/粘贴的代码:
#define RAISE_ERROR_STL(p_strMessage) \
do \
{ \
try \
{ \
std::tstringstream strBuffer ; \
strBuffer << p_strMessage ; \
strMessage = strBuffer.str() ; \
raiseSomeAlert(__FILE__, __FUNCSIG__, __LINE__, strBuffer.str().c_str()) \
} \
catch(...){} \
{ \
} \
} \
while(false)
这使您能够编码:
RAISE_ERROR_STL("Hello... The following values " << i << " and " << j << " are wrong") ;
并且可以生成如下消息:
Error Raised:
====================================
File : MyFile.cpp, line 225
Function : MyFunction(int, double)
Message : "Hello... The following values 23 and 12 are wrong"
请注意,将模板与宏混合可以产生更好的结果(即自动生成与其变量名并排的值)
例如,其他时候,您需要某些代码的 __FILE__ 和/或 __LINE__ 来生成调试信息。以下是Visual C++的经典:
#define WRNG_PRIVATE_STR2(z) #z
#define WRNG_PRIVATE_STR1(x) WRNG_PRIVATE_STR2(x)
#define WRNG __FILE__ "("WRNG_PRIVATE_STR1(__LINE__)") : ------------ : "
与以下代码一样:
#pragma message(WRNG "Hello World")
它会生成如下消息:
C:\my_project\my_cpp_file.cpp (225) : ------------ Hello World
其他时候,您需要使用 # 和 ## 连接运算符生成代码,例如为属性生成 getter 和 setter(这仅适用于非常有限的情况)。
其他时候,如果通过函数使用,您将生成不会编译的代码,例如:
#define MY_TRY try{
#define MY_CATCH } catch(...) {
#define MY_END_TRY }
哪个可以用作
MY_TRY
doSomethingDangerous() ;
MY_CATCH
tryToRecoverEvenWithoutMeaningfullInfo() ;
damnThoseMacros() ;
MY_END_TRY
(不过,我只看到这种代码正确使用过一次)
最后但并非最不重要的,著名的boost::foreach
!!!
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
}
return 0;
}
(注:代码复制/粘贴自 boost 主页)
哪个(恕我直言)比std::for_each
.
因此,宏总是有用的,因为它们超出了正常的编译器规则。但我发现大多数时候我看到一个,它们实际上是 C 代码的剩余部分,从未翻译成正确的 C++。