Це питання дає наочний приклад того, як можна погано використовувати макроси. Щоб побачити інші приклади (і розважитись), дивіться це запитання .
Сказавши це, я наведу приклади реального світу того, що я вважаю гарним включенням макросів.
Перший приклад з'являється в 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 ++, а коли - ні.