Нужно ли мне #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();
}
вы также можете использовать typedef
s:
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
. Вы все еще можете использовать псевдонимы пространства имен typedef
s и using
декларации typedef
s также:
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, которые могут использоваться в случае перекрытия определений макросов. Вы можете нажать предыдущее определение, определить свой собственный, использовать его, и когда вы решите просто поп предыдущее определение.
к сожалению, #define
s не соблюдают правила определения области. #define
s, которые не #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
тем не менее, избегайте их, когда это возможно!
нет. Нет таких вещей, как "местный" #define
s.
область, в которой #define
помещается, неизвестно, в то время как они обрабатываются - ну - препроцессора. (Поэтому вы иногда слышите термин " директива препроцессора "вместо просто"макрос".)