我有两个枚举,如果一个枚举中的一个值与另一个枚举中的一个值同名:
enum A {joe, bob, doc}; enum B {sunday, monday, doc};
编译器(Visual Studio的)抱怨重定义了doc,这意味着它将其视为全局变量。是这样吗?这不是我所期望的行为,它迫使我管理项目中所有枚举元素的名称。任何见解都会有所帮助。
doc
wydwbb8l1#
它不被当作一个全局变量,而是一个全局标识符。更准确地说,它在声明enum的任何名称空间中都被视为标识符。在您的示例中,这是全局名称空间。要了解全局标识符和全局变量之间的区别,请尝试获取枚举的地址。)通常当我定义枚举时,我会在前面加上标识符名称的缩写版本,如下所示:
enum
enum InstrumentType { itStock, itEquityOption, itFutureOption };
这有助于避免碰撞。
v1l68za42#
怀亚特·安德森已经提出
namespace A { enum A {joe, bob, doc}; } namespace B { enum B {sunday, monday, doc}; }
作为对“枚举值与枚举本身在同一作用域中”问题的修复,允许您编写
A::doc; B::doc;
但是,当您希望enum局部于类时,这种解决方案是不可用的,至少在类外部不引入人工命名空间的情况下是不可用的。一个简单的解决方案是将每个enum Package 在一个结构体中,如下所示:
struct A { enum Enum {joe, bob, doc}; }; struct B { enum Enum {sunday, monday, doc}; };
这允许使用与名称空间解决方案相同的用法表示法,
而且还允许
typedef
另外,上面举例说明的 * 命名约定 * 允许
A::Enum
好的,命名约定也可以用于基于命名空间的解决方案......干杯,
oug3syen3#
C++03中的枚举器与枚举有相同的作用域。
enum xxx { yyy, zzz }; ^ ^ ^ enumeration enumerator enumerator
这有时很方便,有时却不太方便。在C++0x中,我们有enum class,它更像C#的enums,同时,假设(因为这是语言规则)yyy和zzz与xxx有完全相同的作用域
enum class
enums
yyy
zzz
xxx
3qpi33ja4#
如果你想让它们成为全局的,通过把你的enum扔到一个命名空间中来解决你的问题并避免命名空间污染:
namespace A { enum A {joe, bob, doc}; } namespace B { enum B {sunday, monday, doc}; } A::doc; B::doc;
e3bfsja25#
枚举的值存在于声明enum的任何作用域中。例如,下面的工作原理是:
enum A {joe, bob, doc}; namespace C { enum B {sunday, monday, doc}; }
或
class A_class { enum A {joe, bob, doc}; }; class B_class { enum B {sunday, monday, doc}; };
dwbf0jvd6#
枚举的值具有枚举本身的作用域,即它的声明作用域。例如:
enum A {value = 30}; int main() { enum B {value = 32}; int x = value; }
x将是32。
zqdjd7g97#
假设我们想要声明一个图形窗口的长宽比,然后按照前面的建议定义枚举值:
struct __aspect_ratio__ { enum values { ASPECT_RATIO_16_9, // HD video ASPECT_RATIO_16_2, // *for testing purposes* ASPECT_RATIO_4_3, // standard monitor ASPECT_RATIO_3_2, // classic film ASPECT_RATIO_21_9, // cinemascope ASPECT_RATIO_1_1 // quadratic window }; }; typedef __aspect_ratio__::values AspectRatio;
最后的typedef允许我们使用AspectRatio::ASPECT_RATIO_16_9作为简写,例如函数签名:
AspectRatio::ASPECT_RATIO_16_9
void SetAspectRatio(AspectRatio aspect) { switch(aspect) { case AspectRatio::ASPECT_RATIO_16_9: // ... default: std::cerr << "Undefined aspect ratio enum value!" << std::endl; } } }
这对我来说就像我在C#中所期望的那样。
假设您使用的是至少C++11,那么最好声明一个enum class:
enum class values { AspectRatio_16_9, // HD video AspectRatio_16_2, // *for testing purposes* AspectRatio_4_3, // standard monitor AspectRatio_3_2, // classic film AspectRatio_21_9, // cinemascope AspectRatio_1_1 // quadratic window };
这是一个类型安全的替代方法,不会污染封闭作用域,还需要注意的是,为了防止名称与全局定义的宏冲突,enum class值通常不应该使用ALL_CAPS命名约定。
ALL_CAPS
7条答案
按热度按时间wydwbb8l1#
它不被当作一个全局变量,而是一个全局标识符。
更准确地说,它在声明
enum
的任何名称空间中都被视为标识符。在您的示例中,这是全局名称空间。要了解全局标识符和全局变量之间的区别,请尝试获取枚举的地址。)
通常当我定义枚举时,我会在前面加上标识符名称的缩写版本,如下所示:
这有助于避免碰撞。
v1l68za42#
怀亚特·安德森已经提出
作为对“枚举值与枚举本身在同一作用域中”问题的修复,允许您编写
但是,当您希望
enum
局部于类时,这种解决方案是不可用的,至少在类外部不引入人工命名空间的情况下是不可用的。一个简单的解决方案是将每个
enum
Package 在一个结构体中,如下所示:这允许使用与名称空间解决方案相同的用法表示法,
而且还允许
typedef
对限定符进行本地类重命名。另外,上面举例说明的 * 命名约定 * 允许
A::Enum
。好的,命名约定也可以用于基于命名空间的解决方案......
干杯,
oug3syen3#
C++03中的枚举器与枚举有相同的作用域。
这有时很方便,有时却不太方便。
在C++0x中,我们有
enum class
,它更像C#的enums
,同时,假设(因为这是语言规则)yyy
和zzz
与xxx
有完全相同的作用域3qpi33ja4#
如果你想让它们成为全局的,通过把你的
enum
扔到一个命名空间中来解决你的问题并避免命名空间污染:e3bfsja25#
枚举的值存在于声明
enum
的任何作用域中。例如,下面的工作原理是:
或
dwbf0jvd6#
枚举的值具有枚举本身的作用域,即它的声明作用域。例如:
x将是32。
zqdjd7g97#
假设我们想要声明一个图形窗口的长宽比,然后按照前面的建议定义枚举值:
最后的
typedef
允许我们使用AspectRatio::ASPECT_RATIO_16_9
作为简写,例如函数签名:这对我来说就像我在C#中所期望的那样。
编辑:
假设您使用的是至少C++11,那么最好声明一个
enum class
:这是一个类型安全的替代方法,不会污染封闭作用域,还需要注意的是,为了防止名称与全局定义的宏冲突,
enum class
值通常不应该使用ALL_CAPS
命名约定。