枚举值的行为类似于全局变量吗?

发布于 2024-10-04 14:22:39 字数 241 浏览 2 评论 0原文

我有两个枚举,如果一个枚举中有一个值与另一个枚举中的值同名:

enum A {joe, bob, doc};
enum B {sunday, monday, doc};

编译器(Visual Studio 的)抱怨 doc 的重新定义,这意味着它会处理它作为全局变量。是这样吗?这不是我期望的行为,它迫使我管理项目中所有枚举元素的名称。

任何见解都会有帮助。

I have two enums, and if there is one value in one enum with the same name as a value in the other enum:

enum A {joe, bob, doc};
enum B {sunday, monday, doc};

The compiler (Visual Studio's) complains about redefinition of doc, which implies it treats it as a global variable. Is this so? It is not the behavior I would expect, and it forces me to manage names of all enum elements in my project.

Any insights would help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

怪我入戏太深 2024-10-11 14:22:39

它不被视为全局变量。变量。它被视为全局标识符。

更准确地说,它被视为声明 enum 的任何命名空间中的标识符。在您的情况下,这就是全局命名空间。

要了解全局标识符和全局变量之间的区别,请尝试获取枚举的地址。 ;)

通常,当我定义枚举时,我会在前面添加标识符名称的缩写版本。像这样:

enum InstrumentType { itStock, itEquityOption, itFutureOption };

这有助于避免碰撞。

It's not treated as a global variable. It's treated as a global identifier.

More precisely, it's treated as an identifier in whatever namespace the enum is declared in. In your case, that's the global namespace.

For an idea of what the difference is between a global identifier and a global variable, try taking the address of your enum. ;)

Usually when I define enums, I prepend the an abbreviated version of the name of the identifier. Like this:

enum InstrumentType { itStock, itEquityOption, itFutureOption };

This helps to avoid collisions.

偏闹i 2024-10-11 14:22:39

Wyatt Anderson 已经建议

namespace A
{
    enum A {joe, bob, doc};
}
namespace B
{
    enum B {sunday, monday, doc};
}

修复“枚举值与枚举本身在同一范围内”问题,允许您编写

A::doc;
B::doc;

但是当您想要本地的 enum 时,此解决方案不可用类,至少在类外部引入人工命名空间的情况下是这样。

一个简单的解决方案是将每个 enum 包装在一个结构中,如下所示:

struct A
{
    enum Enum {joe, bob, doc};
};
struct B
{
    enum Enum {sunday, monday, doc};
};

这允许与命名空间解决方案相同的使用符号,

A::doc;
B::doc;

但它还允许

  • 在类中定义,

  • 通过继承将枚举名称直接带入类,

  • 限定符的本地类重命名,通过 typedef

另外,在我看来,上面示例的命名约定

  • 在引用枚举类型时可以更加清晰,例如编写 A::Enum

好的,命名约定也可以与基于名称空间的解决方案一起使用......

干杯&呵呵,,

Wyatt Anderson has already suggested

namespace A
{
    enum A {joe, bob, doc};
}
namespace B
{
    enum B {sunday, monday, doc};
}

as a fix for the "enum values are in the same scope as the enum itself" problem, allowing you to write

A::doc;
B::doc;

But this solution is not available when you want an enum local to a class, at least not without introducing an artificial namespace outside the class.

A simple solution is to instead wrap each enum in a struct, like so:

struct A
{
    enum Enum {joe, bob, doc};
};
struct B
{
    enum Enum {sunday, monday, doc};
};

This allows the same usage notation as with the namespace solution,

A::doc;
B::doc;

but it additionally allows

  • definition within a class,

  • bringing the enumeration names directly into a class via inheritance, and

  • local-in-class renaming of the qualifier, via typedef.

Plus, the naming convention exemplified above allows

  • in my view, a little extra clarity when referring to an enum type, e.g. writing A::Enum.

OK, the naming convention can also be used with the namespace based solution…

Cheers & hth.,

以往的大感动 2024-10-11 14:22:39

C++03 中的枚举数与枚举具有相同的作用域。

enum     xxx    {    yyy,       zzz       };
          ^           ^          ^ 
    enumeration    enumerator enumerator

这有时很方便,有时则不太方便。

在 C++0x 中,我们将拥有枚举类,它更像 C# 的枚举。同时,假设(因为这是语言规则)yyyzzzxxx 具有完全相同的范围

Enumerators in C++03 have the same scope as the enumeration .

enum     xxx    {    yyy,       zzz       };
          ^           ^          ^ 
    enumeration    enumerator enumerator

This is sometimes convenient, sometimes not really.

In C++0x we will have enum classes which are more like C#'s enums. In the meantime, just assume (cause that's the language rule) that yyy and zzz have exactly the same scope as xxx

捂风挽笑 2024-10-11 14:22:39

如果您希望它们是全局的,请通过将 enum 放入命名空间来解决您的问题并避免命名空间污染:

namespace A
{
    enum A {joe, bob, doc};
}
namespace B
{
    enum B {sunday, monday, doc};
}

A::doc;
B::doc;

If you want them to be global, fix your problem and avoid namespace pollution by throwing your enums in a namespace:

namespace A
{
    enum A {joe, bob, doc};
}
namespace B
{
    enum B {sunday, monday, doc};
}

A::doc;
B::doc;
一场春暖 2024-10-11 14:22:39

枚举的值存在于声明枚举的任何范围内。

例如,以下工作:

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}; };

The values of an enumeration exist in whatever scope the enum was declared in.

The following works, for example:

enum A {joe, bob, doc};
namespace C { enum B {sunday, monday, doc}; }

or

class A_class { enum A {joe, bob, doc}; };
class B_class { enum B {sunday, monday, doc}; };
凯凯我们等你回来 2024-10-11 14:22:39

枚举的值具有枚举本身的范围,即它的声明范围。例如:

enum A {value = 30};

int main()
{
   enum B {value = 32};
   int x = value;
}

x 将为 32。

The enum's values have the scope of the enum itself, that is, it's declaration scope. For example:

enum A {value = 30};

int main()
{
   enum B {value = 32};
   int x = value;
}

x will be 32.

陌路终见情 2024-10-11 14:22:39

假设我们要声明图形窗口的纵横比。然后按照已经建议的方式定义枚举值:

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 作为函数签名的简写:

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 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 命名约定。

Let's say we want to declare aspect ratio for a graphical window. Then defining the enum values as already suggested:

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;

The typedef in the end allows us to use AspectRatio::ASPECT_RATIO_16_9 as a shorthand for, e.g. function signatures:

void SetAspectRatio(AspectRatio aspect)
{
    switch(aspect)
    {
    case AspectRatio::ASPECT_RATIO_16_9:
    // ...
    default:
            std::cerr << "Undefined aspect ratio enum value!" << std::endl;
        }
    }
}

This works for me exactly as I would expect it to in C#.

Edit:

Assuming that you are using at least C++11, then you are better off declaring an 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
};

It's a type-safe alternative that does not pollute the enclosing scope. It should also be noted that, in order to prevent name clashing with globally defined macros, enum class values should usually not use the ALL_CAPS naming convention.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文