有时为了使写入和阅读更容易,我在函数(for example, #define O_REAL Ogre::Real)
中编写了一些本地 #define 宏。
我是否需要 #undef 本地 #define 以确保它保留在某个代码块中?或者当超出范围时会自动 #undef 吗?它是否具有范围的概念?
我不确定 #define 在这种情况下的工作原理。现在,我当然已经尝试了代码并得出了一些结论,但由于我不确定,我想要一些专家意见/建议。
答案 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::Real
,typedef
或float
似乎是double
。您仍然可以使用名称空间别名,typedef
和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;
}
答案 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)