这个问题给出了一个清晰的示例,说明了如何严重使用宏。要查看其他示例(并得到娱乐),请参阅此问题。
话虽如此,我将在现实世界中举例说明我认为很好地合并了宏。
第一个示例出现在CppUnit中,这是一个单元测试框架。像其他任何标准测试框架一样,您创建一个测试类,然后必须以某种方式指定哪些方法应作为测试的一部分运行。
#include <cppunit/extensions/HelperMacros.h>
class ComplexNumberTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( ComplexNumberTest );
CPPUNIT_TEST( testEquality );
CPPUNIT_TEST( testAddition );
CPPUNIT_TEST_SUITE_END();
private:
Complex *m_10_1, *m_1_1, *m_11_2;
public:
void setUp();
void tearDown();
void testEquality();
void testAddition();
}
如您所见,该类的第一个元素是一个宏块。如果我添加了一个新方法testSubtraction
,那么很明显您需要做些什么才能使其包含在测试运行中。
这些宏块扩展为如下所示:
public:
static CppUnit::Test *suite()
{
CppUnit::TestSuite *suiteOfTests = new CppUnit::TestSuite( "ComplexNumberTest" );
suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTest>(
"testEquality",
&ComplexNumberTest::testEquality ) );
suiteOfTests->addTest( new CppUnit::TestCaller<ComplexNumberTest>(
"testAddition",
&ComplexNumberTest::testAddition ) );
return suiteOfTests;
}
您想阅读和维护哪一项?
另一个示例在Microsoft MFC框架中,您可以在其中将函数映射到消息:
BEGIN_MESSAGE_MAP( CMyWnd, CMyParentWndClass )
ON_MESSAGE( WM_MYMESSAGE, OnMyMessage )
ON_COMMAND_RANGE(ID_FILE_MENUITEM1, ID_FILE_MENUITEM3, OnFileMenuItems)
// ... Possibly more entries to handle additional messages
END_MESSAGE_MAP( )
那么,什么是将“好宏”与可怕的邪恶区别开的呢?
他们执行一项无法通过其他任何方式简化的任务。编写宏来确定两个元素之间的最大值是错误的,因为可以使用模板方法来实现相同的目的。但是,有些复杂的任务(例如,将消息代码映射到成员函数)是C ++语言无法很好地处理的。
它们具有极其严格的正式用法。在这两个示例中,宏块都是通过开始和结束宏来声明的,而中间的宏将永远只出现在这些块内部。您拥有普通的C ++,您短暂地使用了一个宏块,然后再次回到普通状态。在“邪恶的宏”示例中,宏散布在整个代码中,不幸的读者无法知道C ++规则何时适用以及何时不适用。