C++从入门到精通——命名空间
命名空间
- 前言
- 一、命名空间
- 引例
- 什么是命名空间
- 二、命名空间定义
- 正常的命名空间定义
- 嵌套的命名空间
- 多个相同名称的命名空间
- 在全局和命名空间定义相同的结构体
- 直接展开命名空间会出现的问题
- 解决办法
- 三、命名空间使用
- 加命名空间名称及作用域限定符
- 带有结构体的命名空间定义结构体变量
- 使用`using`将命名空间中某个成员引入
- 使用`using namespace` 命名空间名称引用
- 引用命名空间和引用头文件有什么区别
- 四、测试代码展示
- namespace.cpp
前言
命名空间是一种用于封装和组织代码的结构,可以避免名称冲突并提供更好的代码组织性。在编程中,命名空间通常用于将相关的类、函数、变量等组织在一起,形成一个独立的逻辑单元。通过使用命名空间,可以更加清晰地组织代码,提高代码的可读性和可维护性。同时,命名空间也可以用于控制访问权限,保护代码的安全性和稳定性。因此,在编程中,合理地使用命名空间是一种重要的编程实践。
一、命名空间
引例
#include #include int rand = 10; // C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决 int main() { printf("%d\n", rand); return 0; } // 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
为什么会出现这种情况呢?是因为在C语言中的stdlib.h中的rand函数和我们定义的变量冲突了,这种情况在C语言中我们只能通过改变参数的名字来解决这种情况,但是在C++完全不用担心这种情况,因为C++中有着命名空间namespace来严格管控函数
什么是命名空间
命名空间顾名思义就是通过定义一个空间来封装变量,函数,是一种用来给变量和函数等标识符起一个独特且有组织的名称的机制。通过使用命名空间,可以避免在不同的代码模块中出现重名的标识符,从而提高代码的可读性和可维护性。
namespace bit { …… }
在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
命名空间是一个用于封装类、函数、变量等代码元素的容器,它提供了一种将相关代码组织在一起的方式,并避免了不同代码之间的命名冲突。在编程中,命名空间的存在使得代码更加清晰、有序,提高了代码的可读性和可维护性。
在C++语言中,命名空间的使用尤为普遍。通过使用命名空间,我们可以将不同模块的代码分隔开来,避免了函数和变量名称的冲突。例如,在C++标准库中,所有的标准函数和类都被定义在一个名为std的命名空间中,这样我们在使用标准库时就需要通过std::前缀来访问其中的元素。
除了C++,其他编程语言也提供了类似命名空间的机制。例如,在Python中,我们可以通过模块来实现类似命名空间的功能。每个模块都是一个独立的命名空间,其中包含了该模块中定义的所有函数、类和变量。当我们在其他模块中导入某个模块时,就可以通过该模块的名称来访问其中的元素,从而避免了命名冲突。
命名空间的使用不仅可以提高代码的可读性和可维护性,还可以帮助我们更好地组织和管理代码。通过将相关的代码元素放在同一个命名空间中,我们可以更加清晰地表达代码之间的逻辑关系,使得代码更加易于理解和维护。
在实际开发中,我们应该充分利用命名空间的特性,合理地组织和管理代码。同时,我们也需要注意避免过度使用命名空间,以免造成代码结构的混乱和复杂性的增加。只有在适当的时候使用命名空间,才能更好地发挥其优势,提高代码的质量和效率。
二、命名空间定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
ps:下文中的bit是我自己定义的,不是只能这样定义,也可以换成其他名称,名称根据自己的喜好定义即可,如果是在项目中,可以按照项目名称来定义
正常的命名空间定义
namespace bit { // 命名空间中可以定义变量/函数/类型 int rand = 10; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; }
嵌套的命名空间
//命名空间可以嵌套 namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } }
多个相同名称的命名空间
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } } namespace N1 { int Mul(int left, int right) { return left * right; } }
上面相同的命名空间将在代码的运行过程中变成下述情况(当然实际的在编译运行的时候肯定不是这样的,但实际意义是一样的,读者可以按照下述来理解)
namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } int Mul(int left, int right) { return left * right; } }
注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
在全局和命名空间定义相同的结构体
在C语言中,可以在全局作用域和命名空间中同时定义相同的结构体,但是它们是不同的结构体类型。这是因为全局作用域中的结构体类型在整个程序中是可见的,而命名空间中的结构体类型只在该命名空间内可见。
下面是一个例子:
#include struct MyStruct { int x; }; namespace Namespace { struct MyStruct { int y; }; } int main() { struct MyStruct globalStruct; Namespace::MyStruct namespaceStruct; globalStruct.x = 10; namespaceStruct.y = 20; std::cout int data; }; namespace MyNamespace { struct MyStruct { int data; }; } using namespace MyNamespace; int main() { MyStruct structVar; // 错误!编译器无法确定是全局结构体还是命名空间中的结构体 return 0; } int data; }; namespace MyNamespace { struct MyStruct { int data; }; } int main() { MyStruct globalStruct; // 访问全局结构体 MyNamespace::MyStruct namespaceStruct; // 访问命名空间中的结构体 return 0; } // 命名空间中可以定义变量/函数/类型 int a = 0; int b = 1; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; } int main() { // 编译报错:error C2065: “a”: 未声明的标识符 printf("%d\n", a); return 0; } int a = 1; // 编译报错:error C2065: “a”: 未声明的标识符 printf("%d\n", a); return 0; } printf("%d\n", N::a); //打印嵌套命名空间printf("%d\n", N::N1::a); return 0; } struct MyStruct { int value; }; } int main() { using namespace std; MyNamespace::MyStruct myVar; //也可以是下述情况 struct MyNamespace::MyStruct n1; //不能是MyNamespace::struct MyStruct myVar; myVar.value = 10; n1.value = 20; cout printf("%d\n", N::a); printf("%d\n", b); return 0; } printf("%d\n", N::a); printf("%d\n", b); Add(10, 20); return 0; } // printf("%d\n", rand); // return 0; //} // 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数” //#include // 命名空间中可以定义变量/函数/类型 int rand = 10; int Add(int left, int right) { return left + right; } struct Node { struct Node* next; int val; }; } //命名空间可以嵌套 namespace N1 { int a; int b; int Add(int left, int right) { return left + right; } namespace N2 { int c; int d; int Sub(int left, int right) { return left - right; } } } namespace N1 { int Mul(int left, int right) { return left * right; } } //namespace bit //{ // // 命名空间中可以定义变量/函数/类型 // int a = 0; // int b = 1; // int Add(int left, int right) // { // return left + right; // } // struct Node // { // struct Node* next; // int val; // }; //} struct MyStruct { int data; }; namespace MyNamespace { struct MyStruct { int data; }; } //using namespace MyNamespace; int main() { MyStruct structVar; // 错误!编译器无法确定是全局结构体还是命名空间中的结构体 return 0; } //int main() //{ // // // 编译报错:error C2065: “a”: 未声明的标识符 // printf("%d\n", N1::a); // return 0; //} //int main() //{ // using namespace bit; // using std::cout; // using std::cin; // int i, j; // cout
- namespace.cpp