Нужно ли мне #undef локальное #define? Есть ли такая вещь, как локальное определение?

иногда, чтобы сделать вещи проще писать и читать, я пишу некоторые местные #define макросы в функции (for example, #define O_REAL Ogre::Real).

Мне нужно #undef местный #define чтобы убедиться, что он остается в пределах определенного блока кода? Или делает это автоматически #undef, когда он выходит за рамки? Есть ли у него даже понятие область?

Я не уверен, как #define строительство в этом деле. Теперь я, конечно, экспериментировал с кодом и пришел к определенным выводам, но поскольку я не уверен, я хотел бы получить экспертное мнение/совет.

6 ответов


#define не уважает любую область C++. Нет такого понятия, как "местный" #define. Это будет действовать, пока это #undef-ed. Механизм макросов препроцессора аналогичен функциям "найти и заменить", которые можно найти в большинстве текстовых редакторов; он не уважает содержимое файла.

другими словами, если вы хотите, чтобы ваш #define чтобы быть локальным в определенном блоке кода, Вы должны #undef это в конце этого блока из-за того, что макросы не "понять" сферу.

на самом деле, это одна из самых больших причин, почему макросы не рекомендуется, если они не являются абсолютно необходимыми в C++. Именно поэтому имена макросов обычно вводятся в UPPER_CASE, чтобы указать, что это на самом деле макрос.


на самом деле существует довольно много макро-менее решения для вашей конкретной ситуации. Рассмотрим следующее:

namespace ReallyLongOuterNamespace
{
    namespace ReallyLongInnerNamespace
    {
        class Foo {};
        void Bar() {}
    };
}

void DoThis()
{
    // Too much typing!
    ReallyLongOuterNamespace::ReallyLongInnerNamespace::Foo f;
    ReallyLongOuterNamespace::ReallyLongInnerNamespace::Bar();
}

можно использовать псевдонимы пространства имен:

void DoThis()
{
    namespace rlin = ReallyLongOuterNamespace::ReallyLongInnerNamespace;

    rlin::Foo f;
    rlin::Bar();
}

вы также можете использовать typedefs:

void DoThis()
{
    typedef ReallyLongOuterNamespace::ReallyLongInnerNamespace::Foo MyFoo;

    MyFoo f;
}

вы также можете использовать using объявления:

void DoThis()
{
    using ReallyLongOuterNamespace::ReallyLongInnerNamespace::Foo;
    using ReallyLongOuterNamespace::ReallyLongInnerNamespace::Bar;

    Foo f;
    Bar();
}

вы даже можете использовать комбинацию выше!

void DoThis()
{
    namespace rlin = ReallyLongOuterNamespace::ReallyLongInnerNamespace;
    typedef rlin::Foo MyFoo;
    using rlin::Bar;

    MyFoo f;
    Bar();
}

С уважением Ogre::Real, это typedef на float или double. Вы все еще можете использовать псевдонимы пространства имен typedefs и using декларации typedefs также:

void UseOgre()
{
    typedef Ogre::Real o_Real; // Yes, you can typedef typedefs.
    using Ogre::Real;
    /* Or, you can use:
    namespace o = Ogre;
    typedef o::Real o_Real;
    using o::Real;
    */

    // All equivalent
    Ogre::Real r1;
    o_Real r2;
    Real r3;
    o::Real r4;
}

на объем макроса является частью единицы компиляции, которая приходит после #define, до конца единицы (то есть до конца .cpp file). Однако Visual C++ имеет пару #pragma push_macro/pop_macro, которые могут использоваться в случае перекрытия определений макросов. Вы можете нажать предыдущее определение, определить свой собственный, использовать его, и когда вы решите просто поп предыдущее определение.


к сожалению, #defines не соблюдают правила определения области. #defines, которые не #undef ' D повлияет на весь код после них. Кроме того, если код перед определением того же имени макроса, у вас возникнут проблемы. В C++ вы обычно можете избежать необходимости использовать такие локальные макросы с local typedefs и ссылки. Например, вы можете сделать:

void foo() {
    typedef Ogre::Real O_REAL;
    // ... 
}

этой будет соблюдать правила области. Для переменных можно использовать ссылки:

void foo() {
    int &BAR = Foo::quux::baz::static_bar;
    // ...
}

#define обрабатывается препроцессором, который фактически не знает синтаксис C вообще. #Define игнорирует область и будет оставаться в силе до тех пор, пока вы #undef его или до конца блока компиляции.


нет такой вещи, как local define. Определяет всегда предварительное зло ; -)

для вашего примера я бы порекомендовал typedef чтобы сделать псевдоним для имен переменных

однако, иногда local defines хорошая вещь для программиста (но никогда не для сопровождающего). Чтобы сделать вещи немного проще и немного безопаснее, я всегда undef эти вещи и я даже охраняют свои записи:

#if defined(LOCAL_CROWBAR)
#error Hurgh!
#endif /* LOCAL_CROWBAR */
#define LOCAL_CROWBAR

... use LOCAL_CROWBAR ...

#undef LOCAL_CROWBAR

тем не менее, избегайте их, когда это возможно!


нет. Нет таких вещей, как "местный" #defines.

область, в которой #define помещается, неизвестно, в то время как они обрабатываются - ну - препроцессора. (Поэтому вы иногда слышите термин " директива препроцессора "вместо просто"макрос".)