7.3 名字空间 + 7.3.1 名字空间定义

来源:互联网 发布:电脑软件无缘无故消失 编辑:程序博客网 时间:2024/05/17 20:29

7.3 名字空间

1、名字空间是一个名字可选的声明区域(未命名的名字空间也是合法的)。借助名字空间的名字可访问在名字空间中声明的实体,也就是名字空间的成员。与其它的声明区域不同,名字空间的定义可以由分布在一个多个翻译单元中的多个分立部分组成。

2、翻译单元的最外层声明区域是一个名字空间;参见3.3.5

7.3.1 名字空间定义

1名字空间定义的语法为:

namespace-name:

original-namespace-name

namespace-alias

original-namespace-name:

identifier

 

namespace-definition:

named-namespace-definition

unnamed-namespace-definition

 

named-namespace-definition:

original-namespace-definition

extension-namespace-definition

 

original-namespace-definition:

namespace identifier { namespace-body }

 

extension-namespace-definition:

namespace original-namespace-name { namespace-body }

 

unnamed-namespace-definition:

namespace { namespace-body }

 

namespace-body:

declaration-seqopt

2原始名字空间定义中的标识符必须是在其声明区域中未定义的。原始名字空间定义中的标识符为正被定义的名字空间的名字。在随后的声明区域中,它被当作原始名字空间名

3扩展名字空间定义中的原始名字空间名必须是已经在同一声明区域内的原始名字空间定义中被定义了的。

4、每个名字空间定义都必须位于全局作用域或名字空间作用域(3.3.5)。

5、因为名字空间定义在其定义体(namespace-body)内含有声明,而名字空间定义本身就是一种声明,所以名字空间定义是可以嵌套的。例如:

namespace Outer {

int i;

namespace Inner {

void f() { i++; } // Outer::i

int i;

void g() { i++; } // Inner::i

}

}

7.3.1.1 匿名名字空间

1匿名名字空间定义等价于使用了如下代码:

namespace unique { /* empty body */ }

using namespace unique;

namespace unique { namespace-body }

在同一翻译单元出现的unique都将被相同的标识符替换掉,这个标识符在整个程序范围内是唯一的,既它不同于整个程序中的所有其它标识符。[注:尽管匿名名字空间中的实体能具有外部链接属性,可它被一个和其所在翻译单元相关的唯一标识符所限定,所以在任何其它翻译单元中都是不可见的。]例如:

namespace { int i; } // unique::i

void f() { i++; } // unique::i++

 

namespace A {

namespace {

int i; // A::unique::i

int j; // A::unique::j

}

void g() { i++; } // A::unique::i++

}

 

using namespace A;

void h() {

i++; //error: unique::i or A::unique::i

A::i++; // A::unique::i

j++; // A::unique::j

}

2、不赞成在名字空间作用域内使用static关键字声明对象(参见附录D);匿名名字空间为此提供了一个较好的可替代方案。

7.3.1.2 名字空间成员定义

1、可在名字空间内定义其成员。例如:

namespace X {

void f() { /* ... */ }

}

2、通过显示的限定(3.4.3.2)正被定义的成员名字,也可在具名名字空间之外定义其成员,只要被定义的实体已经在名字空间中声明过,且定义点位于其所属名字空间的外层名字空间内并在其自身的声明之后。例如:

namespace Q {

namespace V {

void f();

}

void V::f() { /* ... */ }          // OK

void V::g() { /* ... */ }          // error: g() is not yet a member of V

namespace V {

void g();

}

}

 

namespace R {

void Q::V::g() { /* ... */ }      // error: R doesn’t enclose Q

}

3、任何在名字空间内首次声明的名字都是这个名字空间的成员。如果一个非局部类的友元声明首次声明了一个类或函数(这意味着类或函数的名字是非限定的),那么这个友元类或函数是最内层嵌套名字空间的成员。友元声明在匹配之前(匹配点可在友元声明所属类声明之前或之后),其名字对于简单名字查找来说是不可见的。当友元函数被调用时,名字查找过程会在其所属名字空间和函数参量关联的类(3.4.2)中搜索函数名字(也就是说,调用友元函数时,同样会考虑参量相关查找。当查找友元类或函数的前向声明时,如果友元类或函数的名字既不是限定名也不是模板标识符,那么不考虑最内嵌套名字空间之外的作用域(如下述代码中的friend void h(int);。例如:

// Assume f and g have not yet been defined.

void h(int);

template <class T> void f2(T);

namespace A {

class X {

friend void f(X);                   // A::f(X) is a friend

class Y {

friend void g();              // A::g is a friend

friend void h(int);         // A::h is a friend

// ::h not considered

friend void f2<>(int);    // ::f2<>(int) is a friend 这行代码在vc6中通不过

                                   // 匹配在全局名字空间中声明的f2模板

};

};

 

// A::f, A::g and A::h are not visible here

X x;

void g() { f(x); }          // definition of A::g 匹配A::X::Y中的友元声明g();

void f(X) { /* ... */}     // definition of A::f 匹配A::X中的友元声明f(X);

void h(int) { /* ... */ }   // definition of A::h 匹配A::X::Y中的友元声明h();

// A::f, A::g and A::h are visible here and known to be friends

}

 

using A::x;

 

void h()

{

A::f(x);

A::X::f(x);       //error: f is not a member of A::X

A::X::Y::g();    // error: g is not a member of A::X::Y

}

原创粉丝点击