using namespace *;(例如using namespace std;)
这个简短奇葩的语句就是用来定义名称空间的啦
来来来,先研究一下为什么要引入名称空间
随着编程语言的发展,C++肯定是要比C更加先进啦,编写C++规则的同胞们也是蛮拼的(致敬)。C是过程性编程而C++是面向对象编程,C++更加复杂。
为了省去不必要的代码(减少函数或者变量所属类的书写),同时为了避免变量或者函数重命名问题(例如多个开发者根据自身爱好来命名函数或变量共同结合成一个组合程序时的冲突问题),引入名称空间来解决这些问题。
比如说一个名称空间可以包含多个变量与函数,不同名称空间包含不同类型的变量和函数,假若两个名称空间中的同一变量名称相同但数值不同,若使用名称空间分别输出两个变量,将会得到两个不同的变量值。引入名称空间来更好的规避名称相同意义不同的使用冲突问题,提高程序的正确性。
1. 例:namespace John
2. {
3. char *say= “I love you”;
4. }
5.
6. // l另一个命名空间 Michael
7. namespace Michael
8. { char *say = “I love you honey”; }
9. int _imain(int argc, _TCHAR* argv[])
10. { cout << John::say << endl; // 输出命名空间John中的字符串
11. cout << Michael::say<< endl; // 输出命名空间Michael中的字符串
12. return 0; }
using namespace *;(这里的*表示可以是任何命名空间)的作用是释放命名空间*中的变量或函数等,使之在被访问时可以不必加“命名空间::”,访问方法与一般的变量或函数无异using namespace *;会给我们书写程序带来方便,但也要慎用,如果释放了多个命名空间中的东西后,它们又可能会引起命名冲突。最好是在使用的几个名称空间中没有相同命名的变量或者函数,否则使用名称空间后得使用“命名空间::”的形式了。减少代码的长度,省事才是名称空间的真谛。
1. #include
2. using namespace std;
3. // 命名空间John
4. namespace John
5. { char *say= “I love you”; }
6. // 命名空间Michael
7. namespace Michael
8. { char *szUrl = “www.jizhuomi.com/software/”; }
9. // 释放命名空间John 和 Michael
10. using namespace JiZhuoMi;
11. using namespace Software;
12. int imain(int argc, _TCHAR* argv[])
13. { cout << say << endl; // 这里会提示编译错误
14. return 0; }
要想正确访问,还需在say前面加上命名空间修饰;
namespace ns1 //指定命名中间nsl
{ int a;
double b; }
namespace是定义命名空间所必须写的关键字,nsl是用户自己指定的命名空间的名字(可以用任意的合法标识符,这里用ns1是因为ns是namespace的缩写,含义请楚),在花括号内是声明块,在其中声明的实体称为命名空间成员(namespace member)。现在命名空间成员包括变量a和b,注意a和b仍然是全局变量,仅仅是把它们隐藏在指定的命名空间中而已。如果在程序中要使用变量a和b,必须加上命名空间名和作用域分辨符“::”,如nsl::a,nsl::b。这种用法称为命名空间限定(qualified),这些名字(如nsl::a)称为被限定名(qualified name)。C++中命名空间的作用类似于操作系统中的目录和文件的关系,由于文件很多,不便管理,而且容易重名,于是人们设立若干子目录,把文件分别放到不同的子目录中,不同子目录中的文件可以同名。调用文件时应指出文件路径。
注意:在头文件中,不要把#include命令放在命名空间中,命名空间中的内容不包括命令行,否则编译会出错。
std准函数库中的函数或对象都要使用std来限定cin,cout定义在命名空间
使用using命名空间成员名
using后面的命名空间成员名必须是由命名空间限定的名字。例如:
using nsl::Student;
以上语句声明:在本作用域(using语句所在的作用域)中会用到命名空间ns1中的成员Student,在本作用域中如果使用该命名空间成员时,不必再用命名空间限定。例如在用上面的using声明后,在其后程序中出现的Student就是隐含地指nsl::Student。
using声明的有效范围是从using语句开始到using所在的作用域结束。
全局命名空间污染(global namespace pollution) 这个名字是不是很有趣哈哈,有没有?
在程序中还往往需要引用一些库(包括C++编译系统提供的库、由软件开发商提供的库或者用户自己开发的库),为此需要包含有关的头文件。如果在这些库中包含有与程序的全局实体同名的实体,或者不同的库中有相同的实体名,则在编译时就会出现名字冲突。 命名空间:实际上就是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。
名称空间的作用:是建立一些互相分隔的作用域,把一些全局实体分隔开来。
使用命名空间别名
可以为命名空间起一个别名(namespace alias),用来代替较长的命名空间名。如
namespace Television //声明命名空间,名为Television{ … }
可以用一个较短而易记的别名代替它。如:
namespace TV=Television; //别名TV与原名Television等价
也可以说,别名TV指向原名Television,在原来出现Television的位置都可以无条件地用TV来代替。
特别值得注意的是,我们在使用std::move时有一条非常重要的规则,就是一定要使用std::move, 而不是using std::move
using std::move;可以让std中的move变得可见,并且作用域同该using语句,这些都没有问题,但是在查找函数名字时,如果函数接受类类型的参数,那么编译器还会在该类所在的命名空间去找该函数的名字,如:
std::string s;
std::cin>>s;
那么当我们使用using std::move;时,如果此时还有另外一个可用的move可见,如
int move(int i) { return 9; } //自定义的move
using std::move;
int main() {
std::cout << move(1); //输出9
return 0;
}
在有局部变量时(例main函数中有与名称空间中命名相同的变量)如不使用“命名空间::”进行操作,编译器优先访问局部变量
命名空间嵌套和其他的嵌套没什么不一样,内层屏蔽外层,在外层使用内层需要域作用符
命名空间内联是c++ 11 的新特性,在命名空间第一次被声明的地方加上inline关键字,则这个命名空间中的名字可以被外层命名空间看见
namespace ns {
inline newEdition {
xxx
}
oldEdition { xx}
}
这样用户在使用ns命名空间中的名字时,可以直接使用新版本的名字,如ns::newName,而非内联则需要ns::oldEdition::oldName;
如果读者想更加详细的了解名称空间可以参考C++ Primer Plus 第六版,这本书解释的很到位(其实这本书其他地方也挺详细的,只不过笔者觉得有些啰。。。这本书还是很适合初学者学习,不瞒你说,笔者学C++就是看的这本书哈哈。。。)
本文部分内容来自网络,仅供参考学习,没有商业利益。。。。。。