2010-02-12 40 views
10

我有一个类和枚举值具有相同的名称。在课堂内部,我想使用提供错误的枚举。有没有办法使用枚举而不用重命名或移动到不同的命名空间?使用类和枚举相同的名称?

例子:

namespace foo { 
    enum bar { 
     BAD 
    }; 

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

哦,请......不能把枚举放在自己的'struct'中以避免冲突,至少? – 2010-02-12 11:46:08

+0

为了提高可读性,我强烈建议为'enum'和'class'选择不同的名称。请记住,一个更好的目标是产生易于维护的软件,而不是在编译器或语言中调用微妙的东西。 – 2010-02-12 17:50:43

回答

9

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

C++中有两个标识符作用域,一个用于类类型和一般标识符作用域。枚举值BAD驻留在通用标识符范围中,而类类型BAR驻留在类标识符范围中。这就是为什么您可以同时使用枚举值和类名的原因:两个名称不会发生冲突。

在类BAD中,标识符查找规则将在找到枚举之前查找类BAD,从而发现错误。现在,如果您完全限定标识符,那么名称查找将首先检查全局标识符范围并匹配枚举值。在另一端,您将不得不添加structclass关键字来声明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,请考虑为类或枚举使用封闭的名称空间或类(更喜欢那里的枚举)。

0

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

5
bar b = foo::BAD; 

,或者如果你是在全局命名空间

bar b = ::BAD; 

但这名超载是不是我推荐。 C++ 0X将允许

bar b = bar::BAD; 

这是一个更好的解决方案,如果依赖于C++ 0X是可以接受的。

作为承诺,说明

9.1/2

如果一个类名称被在一个范围中声明,其中一个对象,功能,或具有相同名称的枚举还声明,那么双方的声明在范围内,类可以被称为仅使用阐述型说明符(3.4.4)

阐述型说明符是形式

class BAD b; 

这对于具有C兼容性,其中标签名称是在一个不同的名称空间,并且必须是[I]的typedef [/ I] ED如果一个要使用它们没有详细阐述,类型 - 符。 (一个众所周知的函数示例是Unix中的struct stat和函数stat)。

这解释了为什么重载名称来指定类和枚举器是可能的。 BAD指定类的原因在于类的名称也被定义为类作用域,并且在成员函数定义中搜索的作用域依次为: - 成员函数作用域 - 类作用域 - 包含类定义的名称空间

在类作用域中发现BAD,因此从不搜索名称空间foo。

+0

有人想知道我是否尝试过。我使用了3种不同的编译器,包括como。这些规则是神秘的,如果我记得有时间的话,我会用参考文献给出更全面的解释。 – AProgrammer 2010-02-12 10:02:21

+0

++,你对此正确 – 2010-02-12 14:39:56

0

这个工程在VS2008,但给出了一个警告:

bar b = bar::BAD; 

它不是我可以推荐。

您应该将枚举放入foo之内的另一个名称空间中,并将barBAD与新命名空间相匹配。

+0

这是C++ 0X语法,如果可用,它是首选解决方案。我的解决方案是C++ 03语法(但使用奥术规则)。 – AProgrammer 2010-02-12 10:03:46