关于C++ 命名空间Namespace 的解析
使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突。在C++中,变量、函数和类都是大量存在的。如果没有命名空间,这些变量、函数、类的名称将都存在于全局命名空间中,会导致很多冲突。比如,如果我们在自己的程序中定义了一个函数toupper(),这将重写标准库中的toupper()函 数,这是因为这两个函数都是位于全局命名空间中的。命名冲突还会发生在一个程序中使用两个或者更多的第三方库的情况中。此时,很有可能,其中一个库中的名 称和另外一个库中的名称是相同的,这样就冲突了。这种情况会经常发生在类的名称上。比如,我们在自己的程序中定义了一个Stack类,而我们程序中使用的某个库中也可能定义了一个同名的类,此时名称就冲突了。
Namespace 关键字的出现就是针对这种问题的。由于这种机制对于声明于其中的名称都进行了本地化,就使得相同的名称可以在不同的上下文中使用,而不会引起名称的冲突。或许命名空间最大的受益者就是C++中的标准库了。在命名空间出现之前,整个C++库都是定义在全局命名空间中的(这当然也是唯一的命名空间)。引入命名空间后,C++库就被定义到自己的名称空间中了,称之为std。这样就减少了名称冲突的可能性。我们也可以在自己的程序中创建自己的命名空间,这样可以对我们认为可能导致冲突的名称进行本地化。这点在我们创建类或者是函数库的时候是特别重要的。
命名空间基础
namespace 关键字使得我们可以通过创建作用范围来对全局命名空间进行分隔。本质上来讲,一个命名空间就定义了一个范围。定义命名空间的基本形式如下:
namespace 名称{//声明}
在命名空间中定义的任何东西都局限于该命名空间内。
下面就是一个命名空间的例子,其中对一个实现简单递减计数器的类进行了本地化。在该命名空间中定义了计数器类用来实现计数;其中的upperbound和lowerbound用来表示计数器的上界和下界。
演示命名空间
- namespace CounterNameSpace
- {
- int upperbound;
- int lowerbound;
- class counter
- {
- int count;
- public:
- counter(int n)
- {
- if ( n <= upperbound ){
- count = n;
- } else {
- count = upperbound;
- }
- }
- void reset(int n)
- {
- if ( n < upperbound )
- {
- count = n;
- }
- }
- int run() {
- if ( count > lowerbound)
- {
- return count--;
- } else {
- return lowerbound;
- }
- }
- };
- }
其中的upperbound,lowerbound和类counter都是有命名空间CounterNameSpace定义范围的组成部分。
在命名空间中声明的标识符是可以被直接引用的,不需要任何的命名空间的修饰符。例如,在CounterNameSapce命名空间中,run()函数中就可以直接在语句中引用lowerbound:
点击(此处)折叠或打开
然而,既然命名空间定义了一个范围,那么我们在命名空间之外就需要使用范围解析运算符来引用命名空间中的对象。例如,在命名空间CounterNameSpace定义的范围之外给upperbound赋值为10,就必须这样写:
CounterNameSpace::upperbound = 10;
或者在CounterNameSpace定义的范围之外想要声明一个counter类的对象就必须这样写:
CounterNameSpace::counter obj;
一般来讲,在命名空间之外想要访问命名空间内部的成员需要在成员前面加上命名空间和范围解析运算符。
下面的程序演示了如何使用CounterNameSpace这个命名空间:
演示命名空间
- #include <iostream>
- using namespace std;
- namespace CounterNameSpace
- {
- int upperbound;
- int lowerbound;
- class counter
- {
- int count;
- public:
- counter(int n)
- {
- if ( n <= upperbound )
- {
- count = n;
- } else
- {
- count = upperbound;
- }
- }
- void reset(int n)
- {
- if ( n < upperbound )
- {
- count = n;
- }
- }
- int run()
- {
- if ( count > lowerbound)
- {
- return count--;
- }
- else
- return lowerbound;
- }
- };
- }
- int main()
- {
- CounterNameSpace::upperbound = 100;
- CounterNameSpace::lowerbound = 0;
- CounterNameSpace::counter ob1(10);
- int i;
- do {
- i = ob1.run();
- cout << i << " ";
- } while (i > CounterNameSpace::lowerbound);
- cout << endl;
- CounterNameSpace::counter ob2(20);
- do {
- i = ob2.run();
- cout << i << " ";
- } while (i > CounterNameSpace::lowerbound);
- cout << endl;
- ob2.reset(100);
- do
- { i = ob2.run();
- cout << i << " ";
- } while (i > CounterNameSpace::lowerbound);
- cout << endl;
- return 0;
- }
请注意:counter类以及upperbound和lowerbound的引用都是在前面加上了CounterNameSpace修饰符。但是,一旦声明了counter类型的对象,就没有必须在对该对象的任何成员使用这种修饰符了。因此ob1.run()是可以被直接调用的。其中的命名空间是可以被解析的。
相同的空间名称是可以被多次声明的,这种声明向相互补充的。这就使得命名空间可以被分割到几个文件中甚至是同一个文件的不同地方中。例如:
点击(此处)折叠或打开
其中命名空间NS被分割成两部分,但是两部分的内容却是位于同一命名空间中的。也就是NS。最后一点:命名空间是可以嵌套的。也就是说可以在一个命名空间内部声明另外的命名空间。
using关键字
如果在程序中需要多次引用某个命名空间的成员,那么按照之前的说法,我们每次都要使用范围解析符来指定该命名空间,这是一件很麻烦的事情。为了解决这个问题,人们引入了using关键字。using语句通常有两种使用方式:
using namespace 命名空间名称;
using 命名空间名称::成员;
第一种形式中的命名空间名称就是我们要访问的命名空间。该命名空间中的所有成员都会被引入到当前范围中。也就是说,他们都变成当前命名空间的一部分了,使用的时候不再需要使用范围限定符了。第二种形式只是让指定的命名空间中的指定成员在当前范围中变为可见。我们用前面的CounterNameSpace来举例,下面的using语句和赋值语句都是有效的:
using CounterNameSpace::lowerbound; //只有lowerbound当前是可见的
lowerbound = 10; //这样写是合法的,因为lowerbound成员当前是可见的
using CounterNameSpace; //所有CounterNameSpace空间的成员当前都是可见的
upperbound = 100; //这样写是合法的,因为所有的CounterNameSpace成员目前都是可见的
下面是我们对之前的程序进行修改的结果:
使用using
- #include <iostream>
- using namespace std;
- namespace CounterNameSpace
- {
- int upperbound;
- int lowerbound;
- class counter
- {
- int count;
- public:
- counter(int n)
- {
- if ( n < upperbound)
- {
- count = n;
- }
- else
- {
- count = upperbound;
- }
- }
- void reset( int n )
- {
- if ( n <= upperbound )
- {
- count = n;
- }
- }
- int run()
- {
- if ( count > lowerbound )
- {
- return count--;
- }
- else
- {
- return lowerbound;
- }
- }
- };
- }
- int main()
- {
- //这里只是用CounterNameSpace中的upperbound
- using CounterNameSpace::upperbound;
- //此时对upperbound的访问就不需要使用范围限定符了
- upperbound = 100;
- //但是使用lowerbound的时候,还是需要使用范围限定符的
- CounterNameSpace::lowerbound = 0;
- CounterNameSpace::counter ob1(10);
- int i;
- do
- {
- i = ob1.run();
- cout << i << " ";
- }while( i > CounterNameSpace::lowerbound);
- cout << endl;
- //下面我们将使用整个CounterNameSpace的命名空间
- using namespace CounterNameSpace;
- counter ob2(20);
- do
- {
- i = ob2.run();
- cout << i << " ";
- }while( i > CounterNameSpace::lowerbound);
- cout << endl;
- ob2.reset(100);
- lowerbound = 90;
- do
- {
- i = ob2.run();
- cout << i << " ";
- }while( i > lowerbound);
- return 0;
- }
- 上面的程序还为我们演示了重要的一点:当我们用using引入一个命名空间的时候,如果之前有引用过别的命名空间(或者同一个命名空间),则不会覆盖掉对之前的引入,而是对之前引入内容的补充。也就是说,到最后,上述程序中的std和CounterNameSpace这两个命名空间都变成全局空间了。
- 没有名称的命名空间
- 有一种特殊的命名空间,叫做未命名的命名空间。这种没有名称的命名空间使得我们可以创建在一个文件范围里可用的命名空间。其一般形式如下:
- namespace
- {
- //声明
- }
我 们可以使用这种没有名称的命名空间创建只有在声明他的文件中才可见的标识符。也即是说,只有在声明这个命名空间的文件中,它的成员才是可见的,它的成员才 是可以被直接使用的,不需要命名空间名称来修饰。对于其他文件,该命名空间是不可见的。我们在前面曾经提到过,把全局名称的作用域限制在声明他的文件的一 种方式就是把它声明为静态的。尽管C++是支持静态全局声明的,但是更好的方式就是使用这里的未命名的命名空间。
std命名空间
标准C++把自己的整个库定义在std命名空间中。这就是本书的大部分程序都有下面代码的原因:
using namespace std;
这样写是为了把std命名空间的成员都引入到当前的命名空间中,以便我们可以直接使用其中的函数和类,而不用每次都写上std::。
当然,我们是可以显示地在每次使用其中成员的时候都指定std::,只要我们喜欢。例如,我们可以显示地采用如下语句指定cout:
std::cout << “显示使用std::来指定cout”;
如果我们的程序中只是少量地使用了std命名空间中的成员,或者是引入std命名空间可能导致命名空间的冲突的话,我们就没有必要使用using namespace std;了。然而,如果在程序中我们要多次使用std命名空间的成员,则采用using namespace std;的方式把std命名空间的成员都引入到当前命名空间中会显得方便很多,而不用每次都单独在使用的时候显示指定
转载地址:http://blog.renren.com/share/730973714/7874424429
关于C++ 命名空间Namespace 的解析的更多相关文章
- PHP 命名空间(namespace)
PHP 命名空间(namespace) PHP 命名空间(namespace)是在PHP 5.3中加入的,如果你学过C#和Java,那命名空间就不算什么新事物. 不过在PHP当中还是有着相当重要的意义 ...
- PHP命名空间(Namespace)的使用详解(转)
对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结. 命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只 ...
- PHP命名空间(Namespace)的使用详解
对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结. 命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只 ...
- PHP深入浅出之命名空间(Namespace)的使用详解
对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结. 命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只 ...
- PHP的命名空间namespace
对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结. 命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误.这种情况下只 ...
- XAML实例教程系列 - 命名空间(NameSpace) 三
XAML实例教程系列 - 命名空间(NameSpace) 2012-05-28 14:14 by jv9, 2205 阅读, 10 评论, 收藏, 编辑 上一篇曾提及XAML中,每个对象元素的声明是对 ...
- PHP 命名空间(namespace)定义
PHP 命名空间(namespace) PHP 命名空间(namespace)是在PHP 5.3中加入的,如果你学过C#和Java,那命名空间就不算什么新事物. 不过在PHP当中还是有着相当重要的意义 ...
- Atitit 深入理解命名空间namespace java c# php js
Atitit 深入理解命名空间namespace java c# php js 1.1. Namespace还是package1 1.2. import同时解决了令人头疼的include1 1.3 ...
- PHP 使用命名空间(namespace),实现自动加载
示例: #/DB/MySql.class.php也就是DB文件夹下有MySql.class.php文件 namespace DB; class MySql { public function __co ...
随机推荐
- Android 资源文件local.properties使用以及Gradle文件中的值、Manifests文件中的值
这篇也是因为Gradle存储密钥问题一路填坑总结的,期初连.properties创建都有疑问 因为当时是在Android下查看新建的properties一直没法看到 因为Gradle Scripts是 ...
- jquery拼接字符串
1. $("#div").append("<table><tr align='center'>" +"<td >& ...
- HDU4548 美素数
Problem Description 小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识. 问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素 ...
- [LOJ#525]「LibreOJ β Round #4」多项式
[LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...
- [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)
[LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 …… 接着他们发现自己收 ...
- NOI2017 [NOI2017]游戏 【2-sat】
题目 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用 ...
- javascript之进阶
一 模态框 1 什么是模态框 模态框(Modal)是覆盖在父窗体上的子窗体.指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应.如单击[确定]或[取消]按钮等将该对话框关闭. 2 ...
- VMware 11 安装Mac 10.9
VMware Workstation 11, 10, 9 and 8 Unlocker to Run Mac OS X Guests in Windows 8.1 and 7 VM10装Mac OS ...
- 从0到1:全面理解RPC远程调用
上一篇关于 WSGI 的硬核长文,不知道有多少同学,能够从头看到尾的,不管你们有没有看得很过瘾,反正我是写得很爽,总有一种将一样知识吃透了的错觉. 今天我又给自己挖坑了,打算将 rpc 远程调用的知识 ...
- GridView从行寻找到该控件,以及从该控件获知该行
原文发布时间为:2008-08-01 -- 来源于本人的百度文章 [由搬家工具导入] GridView从行寻找到该控件: protected void Button3_Click(object sen ...