1. C++ 命名空间的引入
一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突。当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突。
例如小李和小韩都参与了一个文件管理系统的开发,它们都定义了一个全局变量 fp,用来指明当前打开的文件,将他们的代码整合在一起编译时,很明显编译器会提示 fp 重复定义(Redefinition)错误。
为了解决合作开发时的命名冲突问题,C++ 引入了命名空间(Namespace)的概念。请看下面的例子:
1. namespace Li{ //小李的变量定义 2. FILE fp = NULL; 3. } 4. namespace Han{ //小韩的变量定义 5. FILE fp = NULL 6. }
小李与小韩各自定义了以自己姓氏为名的命名空间,此时再将他们的 fp 变量放在一起编译就不会有任何问题。
2. 命名空间语法和使用
2.1 定义命名空间
命名空间的定义使用关键字 namespace,后跟命名空间的名称
1. namespace namespace_name { 2. // 代码声明 3. }
用法示例:
1. 2. #include <iostream> 3. using namespace std; 4. 5. // 第一个命名空间 6. namespace first_space{ 7. void func(){ 8. cout << "Inside first_space" << endl; 9. } 10. } 11. // 第二个命名空间 12. namespace second_space{ 13. void func(){ 14. cout << "Inside second_space" << endl; 15. } 16. } 17. int main () 18. { 19. 20. // 调用第一个命名空间中的函数 21. first_space::func(); 22. 23. // 调用第二个命名空间中的函数 24. second_space::func(); 25. 26. return 0; 27. }
当上面的代码被编译和执行时,它会产生下列结果:
1. Inside first_space 2. Inside second_space
2.2 using指令
可以使用 using namespace 指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称。
1. 2. #include <iostream> 3. using namespace std; 4. 5. // 第一个命名空间 6. namespace first_space{ 7. void func(){ 8. cout << "Inside first_space" << endl; 9. } 10. } 11. // 第二个命名空间 12. namespace second_space{ 13. void func(){ 14. cout << "Inside second_space" << endl; 15. } 16. } 17. using namespace first_space; 18. int main () 19. { 20. 21. // 调用第一个命名空间中的函数 22. func(); 23. 24. return 0; 25. }
当上面的代码被编译和执行时,它会产生下列结果:
Inside first_space
using 指令也可以用来指定命名空间中的特定项目。例如,如果您只打算使用 std 命名空间中的 cout 部分,您可以使用如下的语句:
using std::cout;
随后的代码中,在使用 cout 时就可以不用加上命名空间名称作为前缀,但是 std 命名空间中的其他项目仍然需要加上命名空间名称作为前缀。
2.3 嵌套命名空间
命名空间可以嵌套,您可以在一个命名空间中定义另一个命名空间
1. namespace namespace_name1 { 2. // 代码声明 3. namespace namespace_name2 { 4. // 代码声明 5. } 6. }
可以通过使用 :: 运算符来访问嵌套的命名空间中的成员:
1. // 访问 namespace_name2 中的成员 2. using namespace namespace_name1::namespace_name2; 3. 4. // 访问 namespace:name1 中的成员 5. using namespace namespace_name1;
2.4 不连续的命名空间
命名空间可以定义在几个不同的部分中,因此命名空间是由几个单独定义的部分组成的。一个命名空间的各个组成部分可以分散在多个文件中。
所以,如果命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称。
1. //demo1.h 2. #ifndef _DEMO1_H 3. #define _DEMO1_H 4. #include<iostream> 5. namespace demo { 6. void display() { 7. std::cout << "demo1::display" << std::endl; 8. } 9. int num=20; 10. } 11. #endif 12. 13. //demo2.h 14. #ifndef _DEMO2_H 15. #define _DEMO2_H 16. #include <iostream> 17. namespace demo { 18. void display(int a) { 19. std::cout << "demo2::display" << std::endl; 20. } 21. //int num; 因为 demo1.h 中已经声明有同名的变量,取消注释会造成重定义错误 22. } 23. #endif 24. 25. //main.cpp 26. #include <iostream> 27. #include "demo1.h" 28. #include "demo2.h" 29. int main() { 30. demo::display(); 31. demo::display(2); 32. std::cout << demo::num << std::endl; 33. return 0; 34. }
执行结果为:
demo1::display
demo2::display
20
可以看到,demo1.h 和 demo2.h 文件中都定义有 demo 命名空间,当这 2 个头文件被引入到 main.cpp 文件中时,意味着 demo 空间中同时包含 display()、display(int n) 以及 num 这 3 个成员。也就是说,分散在不同文件中的同名命名空间会合并为一个。
再次强调,虽然同一项目的不同文件中可以定义相同的命名空间,但必须保证空间中的成员互不相同,否则编译器会报“重定义”错误。注意,这里的 display() 和 display(int n) 并不会造成重定义,它们互为重载函数。
参考链接:
http://c.biancheng.net/view/7637.html