10.2.2 使用名字空间

在一个名字空间中引用一个名字可以采取两种方法:第一种方法是用作用域运算符,第二种方法是用using指令把所有名字引入到名字空间中。

10.2.2.1 作用域解析

名字空间中的任何名字都可以用作用域运算符作明确地指定,就像引用一个类中的名字一样:

10.2.2 使用名字空间 - 图1

注意定义X:Y:i就像引用一个类Y的数据成员一样容易,Y如同被嵌套在类X中而不像是被嵌套在名字空间X中。

到目前为止,名字空间看上去很像类。

10.2.2.2 使用指令

用using关键字可以让我们立即进入整个名字空间,摆脱输入一个名字空间中完整标识符的烦恼。这种using和namespace关键字的搭配使用称为使用指令(using directive)。using关键字声明了一个名字空间中的所有名字是在当前范围内,所以可以很方便地使用这些未限定的名字。如果以一个简单的名字空间开始:

10.2.2 使用名字空间 - 图2

using指令的用途之一就是把名字空间Int中的所有名字引入到另一个名字空间中,让这些名字嵌套在那个名字空间中。

10.2.2 使用名字空间 - 图3

可以在一个函数中声明名字空间Int中的所有名字,但是让这些名字嵌套在这个函数中。

10.2.2 使用名字空间 - 图4

如果不用using指令,在这个名字空间的所有名字都需要被完全限定。

using指令有一个缺点,那就是看起来不那么直观,引入名字的可见性的范围是在使用using的地方。可以不考虑使用using指令的名字,就像它们已经被全局声明过,现在变为这个范围。

10.2.2 使用名字空间 - 图5

如果有第二个名字空间,它包含了名字空间Math的某些名字:

10.2.2 使用名字空间 - 图6

因为这个名字空间也是用using指令来引入的,这样就可能产生冲突。不过,这种二义性出现在名字的使用时,而不是在using指令使用时。

10.2.2 使用名字空间 - 图7

这样,即使永远不产生歧义性,使用using指令引入带名字冲突的名字空间也是可能的。

10.2.2.3 使用声明

可以用使用声明(using declaration)一次性引入名字到当前范围内。这种方法不像using指令那样把那些名字当成当前范围的全局名来看待,using声明是在当前范围之内进行的一个声明,这就意味着在这个范围内它可以不顾来自using指令的名字。

10.2.2 使用名字空间 - 图8

10.2.2 使用名字空间 - 图9

using声明给出了标识符的完整的名字,但没有了类型方面的信息。也就是说,如果名字空间中包含了一组用相同名字重载的函数,using声明就声明了这个重载的集合内的所有函数。

可以把using声明放在任何一般的声明可以出现的地方。using声明与普通声明只有一点不同:using声明可以引起一个函数用相同的参数类型来重载(这在一般的重载中是不允许的)。当然这种不确定性要到使用时才表现出来,而不是在声明时。

using声明也可以出现在一个名字空间内,其作用与在其他地方时一样:

10.2.2 使用名字空间 - 图10

一个using声明是一个别名,它允许在不同的名字空间声明同样的函数。如果不想由于引入不同名字空间而导致重复定义一个函数时,可以使用using声明,它不会引起任何二义性和重复。