使用同名的类和枚举?

发布于 2024-08-21 11:02:21 字数 253 浏览 1 评论 0原文

我有一个具有相同名称的类和枚举值。在类中我想使用给出错误的枚举。有没有什么方法可以使用枚举而无需重命名或移动到不同的名称空间?

例子:

namespace foo {
    enum bar {
        BAD
    };

    class BAD {
        void worse () {
            bar b = BAD; // error
        }
    };
};

I've a class and an enum value which have the same name. Inside the class I want to use the enum which gives an error. Is there any way to use the enum without renaming or moving to a different namespace?

Example:

namespace foo {
    enum bar {
        BAD
    };

    class BAD {
        void worse () {
            bar b = BAD; // error
        }
    };
};

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

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

发布评论

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

评论(4

所有深爱都是秘密 2024-08-28 11:02:21

这是执行名称查找的棘手部分之一。

C++ 中有两种标识符作用域,一种用于类类型,一种用于通用标识符作用域。枚举值 BAD 驻留在通用标识符范围内,而类类型 BAR 驻留在类标识符范围内。这就是为什么允许您同时拥有一个枚举值和一个具有相同名称的类的原因:两个名称不会冲突。

在类 BAD 中,标识符查找规则将在找到枚举之前先找到类 BAD,从而导致错误。现在,如果您完全限定标识符,则名称查找将首先检查全局标识符范围并匹配枚举值。另一方面,您必须添加 struct 或 class 关键字来声明 BAD 类型的变量。

namespace foo {
   enum bad { BAD; };
   class BAD {
      void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum
   };
}
int main() {
   // foo::BAD b;    // error, foo::BAD is an enum, not a type
   class foo::BAD b; // correct
}

现在,我建议反对这种用法。重复使用这样的标识符通常不是一个好主意。代码会更加复杂,并且可能会误导普通读者(相同的非限定标识符在不同的上下文中使用时指的是不同的事物)。如果名称确实需要是BAD,请考虑为类或枚举使用封闭的命名空间或类(最好使用枚举)。

This is one of those tricky parts of how the name lookup is performed.

There are two identifier scopes in C++, one for class types and general identifier scope. The enum value BAD resides in the general identifier scope, while the class type BAR resides in the class identifier scope. That is the reason why you are allowed to have both an enum value and a class with the same name: both names do not collide.

Within class BAD, the identifier lookup rules will find the class BAD before it finds the enum, and thus the error. Now, if you fully qualify the identifier then the name lookup will first check the global identifier scope and match the enum value. On the opposite end, you will have to add the struct or class keyword to declare variables of type BAD.

namespace foo {
   enum bad { BAD; };
   class BAD {
      void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum
   };
}
int main() {
   // foo::BAD b;    // error, foo::BAD is an enum, not a type
   class foo::BAD b; // correct
}

Now, I would advice against this usage. It is generally not a good idea to reuse an identifier like this. Code will be more complex, and probably misleading for the casual reader (the same unqualified identifier refers to different things when used in different contexts). If the names do need to be BAD, consider using an enclosing namespace or class for either the class or the enum (prefer the enum there).

朦胧时间 2024-08-28 11:02:21
 bar b = foo::BAD;

或者如果您位于全局命名空间中,

 bar b = ::BAD;

但我不建议使用该名称重载。 C++0X 将允许

 bar b = bar::BAD;

如果对 C++0X 的依赖性可以接受,

哪个是更好的解决方案。正如所承诺的,解释

9.1/2

如果在一个范围内声明了一个类名,同时还声明了同名的对象、函数或枚举器,则两个声明都在范围内,则只能使用详细类型来引用该类-说明符 (3.4.4)

elaborated-type-specifier 的形式是

class BAD b;

这样,这是为了与 C 兼容,其中标记名称位于不同的命名空间中,并且必须是 [i]typedef[/i]如果想在没有详细类型说明符的情况下使用它们,请编辑。 (一个众所周知的函数示例是 Unix 中的 struct stat 和函数 stat)。

这就解释了为什么可以重载名称来指定类和枚举器。 BAD 在这里指定类的原因是类的名称也定义到类作用域中,并且在成员函数定义中搜索的作用域是按顺序排列的:
- 成员函数作用域
- 类范围
- 包含类定义

BAD 的命名空间在类范围内找到,因此永远不会搜索命名空间 foo。

 bar b = foo::BAD;

or if you are in the global namespace

 bar b = ::BAD;

but that name overloading is not something I'd recommend. C++0X will allow

 bar b = bar::BAD;

which is a better solution if the dependency on C++0X is acceptable.

As promised, the explanation

9.1/2

If a class name is declared in a scope where an object, function, or enumerator of the same name is also declared, then both declarations are in scope, the class can be referred to only using an elaborated-type-specifier (3.4.4)

The elaborated-type-specifier is the form

class BAD b;

This is for compatibility with C where tag names are in a different name space and must be [i]typedef[/i]ed if one want to use them without an elaborated-type-specifier. (A well known example with a function is the struct stat and the function stat in Unix).

That explain why the overloading of a name to designate a class and an enumerator is possible. The reason for which BAD designate the class here is that the name of the class is also defined into the class scope and in a member function definition the scope searched are in order:
- the member function scope
- the class scope
- the namespace containing the class definition

BAD is found at class scope, so the namespace foo is never searched.

友谊不毕业 2024-08-28 11:02:21

不,没有办法做到这一点。您应该使用有效的标识符。有效标识符意味着您必须能够识别它。 :)

No, there is no way to do that. You should use valid identifier. Valid identifier means that you have to be able to identify with it. :)

耶耶耶 2024-08-28 11:02:21

这在 VS2008 中有效,但给出了一个警告:

bar b = bar::BAD;

它不是我可以推荐的。

您应该将枚举放在 foo 内的另一个命名空间中,并使用新命名空间限定 barBAD

This works in VS2008, but gives a warning:

bar b = bar::BAD;

Its not something I can recommend.

You should put the enum within another namespace inside foo and qualify both bar and BAD with the new namespace.

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