C++ 我需要#取消定义本地#定义吗?有没有地方性的定义?

C++ 我需要#取消定义本地#定义吗?有没有地方性的定义?,c++,c-preprocessor,C++,C Preprocessor,有时,为了使编写和阅读更容易,我在函数中编写了一些本地#define宏(例如,#define O#u REAL Ogre::REAL) 我是否需要#取消定义本地#定义,以确保它位于某个代码块内?或者当它超出范围时会自动取消定义?它甚至有范围的概念吗 我不确定在这种情况下如何定义。现在,我当然已经对代码进行了实验,并得出了某些结论,但由于我不确定,我想要一些专家意见/建议。不。没有“本地”定义之类的东西 #define的作用域在-well-preprocessor处理时是未知的。(因此,有时您听到

有时,为了使编写和阅读更容易,我在函数
中编写了一些本地#define宏(例如,#define O#u REAL Ogre::REAL)

我是否需要#取消定义本地#定义,以确保它位于某个代码块内?或者当它超出范围时会自动取消定义?它甚至有范围的概念吗


我不确定在这种情况下如何定义。现在,我当然已经对代码进行了实验,并得出了某些结论,但由于我不确定,我想要一些专家意见/建议。

不。没有“本地”定义之类的东西

#define
的作用域在-well-preprocessor处理时是未知的。(因此,有时您听到的术语是“预处理器指令”而不是“宏”)。

< P> <代码>定义> <代码>不尊重任何C++范围。没有所谓的“本地”定义。预处理器的宏机制就像大多数文本编辑器中的“查找并替换”功能一样;它不尊重文件的内容

换句话说,如果希望
#define
在某个代码块中是本地的,则必须
#undef
将其放在该块的末尾,因为宏不“理解”范围

事实上,这是为什么宏不被阻止的最大原因之一,除非它们在C++中是绝对必要的。这就是为什么宏名通常以大写形式输入,以表明它实际上是一个宏


对于您的具体情况,实际上有很多无宏观的解决方案。考虑以下事项:

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

void DoThis()
{
    // Too much typing!
    ReallyLongOuterNamespace::ReallyLongInnerNamespace::Foo f;
    ReallyLongOuterNamespace::ReallyLongInnerNamespace::Bar();
}
可以使用命名空间别名:

您还可以使用
typedef
s:

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

    MyFoo f;
}
您还可以使用
声明:

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
,对于
float
double
,它似乎是
typedef
。您仍然可以使用命名空间别名,
typedef
s和
使用
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由预处理器处理,它实际上根本不知道C语法。定义忽略作用域,并将一直有效,直到您取消定义它或直到编译单元结束

没有所谓的
本地定义
。 定义总是暂时的邪恶;-)

对于您的示例,我建议
typedef
为变量名创建别名

然而,有时
localdefines
对程序员来说是件好事(但对维护人员来说永远不是好事)。为了让事情变得更简单、更安全,我总是
undef
这些东西,我甚至保护它们的入口:

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

... use LOCAL_CROWBAR ...

#undef LOCAL_CROWBAR
然而,尽可能避免这些

宏的作用域是编译单元的一部分,它位于#define之后,直到单元结束(也就是说,直到.cpp文件结束)。但是VisualC++有一对“SypRead MaPuxMyGrime/Popu宏”,可以在宏定义重叠的情况下使用。您可以推送上一个定义,定义自己的定义,使用它,当您决定只弹出上一个定义时。

不幸的是,
#define
不遵守范围规则<代码>#定义
未定义的
#未定义
'd将影响它们之后的所有代码。此外,如果在定义相同宏名称之前先编写代码,则会出现问题。在C++中,通常可以避免使用本地宏,使用本地代码“Type”、“Debug”、“代码”和引用。例如,您可以执行以下操作:

void foo() {
    typedef Ogre::Real O_REAL;
    // ... 
}
这将尊重范围界定规则。对于变量,可以使用引用:

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