可能重复:
How do you import an enum into a different namespace in C++?
如何解决以下枚举命名空间问题?
namespace A {
typedef enum ABar { a, b };
void foo( ABar xx ) {}
}
namespace B {
typedef enum A::ABar BBar;
void foo( BBar xx ) { A::foo( xx ); }
}
int main() {
B::foo( B::a ); // 'a' : is not a member of 'B'
// 'a' : undeclared identifier
}
答案 0 :(得分:8)
在键入类型时,不会导入该命名空间中定义的符号。所以,虽然你可以写:
int main() {
B::BBar enumVariable=A::a;
}
由于此符号不存在,您无法访问B::a
。
部分漫游,在我看来,一种使代码更干净的方法,尽管编写时间更长,但是将每个枚举打包到它自己的结构中,例如:
struct ABar {
enum Type {a, b};
};
typedef ABar BBar;
int main() {
ABar::Type var=ABar::a;
BBar::Type var2=BBar::a;
}
如果你仍然需要它,你将能够将ABar打包到命名空间中,并且通常也在另一个命名空间中输入typedef。
答案 1 :(得分:4)
问题是枚举的声明不仅创建了类型,而且还声明了具有给定值的枚举标识符。当您执行typedef时,您只是为该类型创建一个本地别名,但这些值不会被带到新的命名空间。也就是说,编译器将看到B::BBar
,并且它将通过您引用A::ABar
的typedef来了解。但是在处理B::a
时,B
命名空间中没有任何内容引用该内容。
要实现这一点,您必须将a
和b
带入新命名空间,而typedef不会这样做,因为它们不是类型。无论如何它是可实现的,如:
namespace A {
enum ABar {
a, b
};
}
namespace B {
typedef ::A::ABar BBar;
using ::A::a;
using ::A::b;
}
我不建议这样做,因为它会很快成为一个维护问题(你必须记住每次更改原始命名空间时都要更新这两个命名空间。
至于如何处理这个问题,@ CygnusX1提出的解决方法实际上是一个很好的选择,如果你使用的是C ++ 0x编译器,那么该语言允许使用类似的习惯用法,因为它允许访问枚举值通过枚举类型:
namespace A {
enum ABar { a,b };
}
namespace B {
typedef A::ABar BBar;
}
int main() {
std::cout << B::BBar::a << std::endl; // extra enum qualification
}
答案 2 :(得分:2)
您无法输入定义枚举。你可以使用它:
namespace B {
using A::ABar;
}
修改强>
以下是修改后的示例:
namespace A {
enum ABar { a, b };
void foo( ABar xx ) {}
}
namespace B {
using A::ABar; // 'ABar' : is injected into namespace 'B'
using A::a; // 'a' : is injected into namespace 'B'
void foo( ABar xx ) { A::foo( xx ); }
}
int main() {
B::foo( B::a );
}
然而,正如CygnusX1和David指出的那样,上面是污染命名空间B,最好这样做:
namespace A {
enum ABar { a, b };
void foo( ABar xx ) {}
}
namespace B {
void foo( A::ABar xx ) { A::foo( xx ); }
}
int main() {
B::foo( A::a );
}
还有第三个选项,可以键入它,但是正确:
namespace B {
typedef A::ABar BBar;
void foo( BBar xx ) { A::foo( xx ); }
}
但你仍然不能这样做:
B::foo( B::a ); // 'a' : is not a member of 'B'
// 'a' : undeclared identifier
因为BBar只是A :: ABar的别名。