我需要#undef本地#define吗?是否存在本地定义?

时间:2011-02-20 09:04:28

标签: c++ c-preprocessor

有时为了使写入和阅读更容易,我在函数(for example, #define O_REAL Ogre::Real)中编写了一些本地 #define 宏。

我是否需要 #undef 本地 #define 以确保它保留在某个代码块中?或者当超出范围时会自动 #undef 吗?它是否具有范围的概念?

我不确定 #define 在这种情况下的工作原理。现在,我当然已经尝试了代码并得出了一些结论,但由于我不确定,我想要一些专家意见/建议。

6 个答案:

答案 0 :(得分:25)

#define不尊重任何C ++范围。没有“本地”#define这样的东西。它将在#undef编辑之前生效。预处理器的宏机制就像大多数文本编辑器中的“查找和替换”功能一样;它不尊重文件的内容。

换句话说,如果您希望#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::Realtypedeffloat似乎是double。您仍然可以使用名称空间别名,typedefusing声明与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;
}

答案 1 :(得分:2)

宏的范围是#define之后的编译单元的一部分,直到单元结束(也就是说,直到.cpp文件结束)。但是,Visual C ++有一对#pragma push_macro / pop_macro,可用于宏定义重叠的情况。您可以推送先前的定义,定义自己的定义,使用它,以及何时决定弹出以前的定义。

答案 2 :(得分:2)

不幸的是,#define不尊重范围规则。不#define'的#undef会影响其后的所有代码。此外,如果在您定义相同的宏名称之前的代码,您将遇到问题。在C ++中,您通常可以避免使用本地typedefs和引用的本地宏。例如,你可以这样做:

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

尊重范围规则。对于变量,您可以使用引用:

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

答案 3 :(得分:1)

#define 由预处理器处理,它实际上根本不知道C语法。 #define忽略范围,并且在#undef它或直到编译单元结束之前一直有效。

答案 4 :(得分:1)

答案 5 :(得分:0)