7.3 名字空间 + 7.3.1 名字空间定义
2006-04-19 14:53
435 查看
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
}
相关文章推荐
- 7.3 名字空间 + 7.3.1 名字空间定义
- 关于包含头文件而编译时却一个未定义错误的原因(未使用命名名字空间)
- qt开发环境 - c++之输入,输出,名字空间定义,名字空间指令,名字空间声明
- js名字空间未定义的错误
- 「命名空间内部使用的名字的查找」与「类成员定义中使用的名字的查找」的区别
- XPath遇上命名空间(注意,就算是用默认命名空间的节点,也要为命名空间定义一个名字,并使用这个名字)
- C++ 关于声明,定义,类的定义,头文件作用,防止头文件在同一个编译单元重复引用,不具名空间
- Qt中Ui名字空间以及setupUi函数的原理和实现
- 对C++的基本认识之名字空间域
- 命名空间的定义与使用
- 杂货边角(22):名字空间namespace的一二事
- 重温《C++ Primer》笔记五 类定义中成员函数的名字隐藏(虚函数与非虚函数)
- 命名空间定义PHP 5.3中的命名空间:你用过了么?
- xml学习5-名字空间
- 未命名名字空间
- C++引入名字空间(namespace)意义何在?为什么using namespace std会成为常用语句?
- 名字空间
- 【PHP高级】自动装载与名字空间
- JDOM操作XML文档高级篇XML验证,创建带名字空间的xml, xml文档的修改
- effective c++ 条款28: 划分全局名字空间