在做项目的过程中,遇到了一个问题,在名称空间A::B和C::D中分别定义了枚举型变量
namespace A
{
namespace B
{
EUNM NumType
{
TYPE1 = 0;
TYPE2 = 1;
}
}
}
namespace C
{
namespace D
{
EUNM NumType
{
TYPE1 = 0;
TYPE2 = 1;
}
}
}
然后在程序中调用TYPE1
using namespace A::B; //声明A::B空间的所有名称可用,而不需要作用域解析运算符
using namespace C::D; //声明A::B空间的所有名称可用,而不需要作用域解析运算符
NumType type = TYPE1;
却会报错
error C2872:"TYPE1"不明确的字符
因此查阅了C++ Primer Plus,了解有关命名空间的使用方法
(1)传统C++的命名空间
声明区域 | 在函数外声明全局变量,声明区域为所在文件; 在函数中声明的变量,声明区域为声明所在代码块 |
潜在作用域 | 从声明点开始,到声明区域的结尾 |
C++关于全局变量和局部变量的规则定义了一个名称层次空间。在一个函数中声明的全局变量不会与在另一个函数中声明的局部变量发生冲突。
(2)新的名称空间特性
C++新增了一个功能,通过定义一种新的声明区域来创建命名的名称空间,一个名称空间中的名称不会与另一个名称空间中的相同名称发生冲突。
namespace Jack{
double pail;
void fetch();
}
注:
Ⅰ、命名空间可以是全局的,也可以位于另一个命名空间中,但不能位于代码块中
namespace elements
{
namespace fire
{
...
}
}
Ⅱ、名称空间是开放的,即可以把名称加入到已有的名称空间中
namespace Jack{
void fetch()
{
...
}
} //为原型函数提供代码
using声明和编译指令
a、using声明
using声明由被限定的名称和前面的关键字组成,using声明将特定的名称添加到它所属的声明区域中。
using Jill::fetch
声明完成后,可使用fetch替代Jill::fetch
b、using编译
using namespace Jack;
在全局声明区域中使用using编译指令,使该名称空间的名称全局可用,而不需要使用作用域解析运算符。
在函数中使用using编译指令,将是其中的函数在该函数中可用。
注:一般来说,使用using声明比using编译更加安全,这是由于它只导入特定的名称。如果该名称与局部名称发生冲突,编译器会提示。using编译指令导入所有名称,若与局部名称发生冲突,局部名称将覆盖名称空间版本,编译器并不会发出警告。
c、名称空间的嵌套
可以在名称空间中使用using编译指令和using声明。
namespace myth
{
using Jill::fetch;
using namespace elements;
using std::out;
}
using编译指令是可传递的
using namespace myth;
//等价于
using namespace myth;
using namespace elements;
可以给命名空间创建别名,例如
namespace ME = myth::elements;
d、未命名的名称空间
可以通过省略名称创建未命名的名称空间。由于这种命名空间没有名称,不能显示的使用using指令来声明它在其他位置可用。这提供了连接未内部静态变量的替代品。
namespace
{
int ice;
int bandycoot;
}
//可用来替换
static int ice;
static int bandcoot;
(3)名称空间及其使用
随着名称空间的推广,逐渐出现一些统一的编程理念,下面是一些指导原则。
Ⅰ、使用已命名的名称空间中声明的变量,而不是使用外部全局变量
Ⅱ、使用已命名的名称空间中声明的变量,而不是使用静态全局变量
Ⅲ、不在头文件中使用using编译指令。首先,这掩盖了要让那些名称可用;另外,头文件包含顺序会影响程序行为。
Ⅳ、对于using声明,首选作用域是局部而不是全局
Ⅴ、如果开发了一个函数库或者类库,将其放在一个命名空间中。
别忘了,使用命名空间的主旨是为了简化大型编程项目的管理工作。对于简单程序,使用using编译并非不可以。
最后使用域名解析符调用TYPE1,问题成功解决
NumType type = A::B::TYPE1;
参考文献
1、c++primer plus第六版