この質問は、マクロを不適切に使用する方法の明確な例を示しています。他の例を見る(そして楽しませる)には、この質問を参照してください。
そうは言っても、マクロを適切に組み込むことができると考えるものの実例を紹介します。
最初の例は、ユニットテストフレームワークである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( )
それでは、「良いマクロ」と恐ろしい悪の種類を区別するものは何ですか?
他の方法では単純化できないタスクを実行します。テンプレートメソッドを使用して同じことを実現できるため、2つの要素間の最大値を決定するマクロを記述するのは間違っています。しかし、いくつかの複雑なタスク(たとえば、メッセージコードのメンバー関数へのマッピング)があり、C ++言語ではうまく処理されません。
それらは非常に厳密で正式な使用法を持っています。これらの例の両方で、マクロブロックはマクロの開始と終了によってアナウンスされ、中間のマクロはこれらのブロック内にのみ表示されます。通常のC ++があり、簡単にマクロのブロックで言い訳をした後、再び通常に戻ります。「邪悪なマクロ」の例では、マクロはコード全体に散らばっており、不運な読者には、C ++ルールがいつ適用されるか、いつ適用されないかを知る方法がありません。