C++的命名空间
目录
命名冲突
运行下面两端代码:
#include <stdio.h>
int rand = 10;
int main()
{
printf("hello world\n");
printf("%d\n", rand);
return 0;
}
#include <stdio.h>
#include <stdlib.h> //新增包含头文件
int rand = 10;
int main()
{
printf("hello world\n");
printf("%d\n", rand);
return 0;
}
我们会发现不包含stdlib头文件之前的代码可以正常执行,包含了stdlib头文件的代码会报错:
这是因为rand是stdlib头文件中一个被定义的函数,而int rand是对rand函数的重定义,因此可以得到这样的结论:c语言的全局变量会出现命名冲突的问题。
命名冲突发生的对象一般是程序员与库(标准库或第三方库)、程序员与程序员之间(项目中二人起了相同的变量或函数名)
域
c/c++中有域的概念,①处的x属于全局域,②处的x属于局部域,当我们使用变量x时会优先采用局部域的值,即局部域优先原则(因此执行下面代码的结果为1)
#include <stdio.h>
①int x = 0;//全局域
int main()
{
②int x = 1;//局部域
printf("hello world\n");
printf("%d\n", x);
return 0;
}
域作用限定符::
作用:自主选择要使用哪个域中的变量
使用方式:域名::变量名
c++主要有全局域、局部域、命名空间域、类域的概念
注意事项:
1、域名为空时默认为全局域
2、读取局部域时一般不使用该符号,因为局部域优先原则,读取时肯定先读局部域
#include <stdio.h>
int x = 0;
int main()
{
int x = 1;
printf("hello world\n");
printf("%d\n", ::x);
return 0;
}
命名空间域
作用:实现重名变量的共存(解决命名冲突)
命名空间的定义
格式:namespace 命名空间域名 {变量名}
1、只能定义在全局
#include <stdio.h>
namespace bit1
{
int x = 0;
}
namespace bit2
{
int x = 1;
}
int main()
{
printf("%d\n", x);
printf("%d\n", x);
return 0;
}
运行上述代码后仍然报错,这是因为编译器在编译时会按如下顺序对变量进行搜索:
①当前局部域
②全局域
③指定的命名空间域
#include <stdio.h>
namespace bit1
{
int x = 0;
}
namespace bit2
{
int x = 1;
}
int main()
{
printf("%d\n", bit1::x);
printf("%d\n", bit2::x);
return 0;
}
至此,我们在刚开始产生的rand函数问题也可以得到解决:
#include <stdio.h>
#include <stdlib.h>
namespace bit1
{
int x = 0;
int rand = 10;
}
namespace bit2
{
int x = 1;
}
int main()
{
printf("%d\n", bit1::x);
printf("%d\n", bit2::x);
printf("%d\n", bit1::rand);
return 0;
}
2、命名空间域中可以定义变量/函数/类型
namespace bit1
{
int x = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
3、 同一项目中允许存在多个相同名称的命名空间,编译器最后会将它们合并
//test.h头文件
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
}
//TEST.h头文件
namespace N1
{
int rand = 10;
}
//合并后
namespace N1
{
int Mul(int left, int right)
{
return left * right;
}
int rand = 10;
}
4、命名空间域可以嵌套
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;
}
}
}
小补充(一)
在未指定命名空间域前,报错的内容是x未定义而不是重定义,这就证明被命名空间域包括的变量虽然是全局变量(仍然可以整个程序被访问)但是不处于全局域中,以下是三种域对变量的影响:
域名 | 是否对声明周期产生影响 | 是否对变量的访问产生影响 |
全局域 | 是 | 否 |
局部域 | 是 | 否 |
命名空间域 | 否 | 否 |
命名空间的使用
1、不使用using的指定访问
特点:用哪个声明哪个(命名空间::内容名)
#include <iostream>
namespace N
{
int a = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
printf("%d\n", N::a);
return 0;
}
2、使用using的指定访问
特点:提前打招呼,下次再用就不需要声明 (using 命名空间::内容名)
#include <iostream>
namespace N
{
int a = 10;
int b = 20;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
3、命名空间的全部展开
特点: 将整个命名空间中的内容全部可以直接访问
#include <iostream>
namespace N
{
int a = 10;
int b = 20;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
using namespace N;
int main()
{
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", Add(10, 20));
return 0;
}
缺点:
-
潜在命名冲突(重点):如果多个命名空间中有相同名称的标识符(如变量、函数等),使用
using namespace
可能会导致名称冲突。这会使代码难以理解和维护。 -
可读性降低:展开整个命名空间可能使代码更加难以阅读,因为读者无法轻易知道特定标识符是来自哪个命名空间。
-
潜在影响全局范围:如果将所有内容都引入当前作用域,可能会意外地影响全局范围内其他部分或第三方库中的同名标识符。
-
编译时间增加:当涉及到大型项目时,在编译时需要处理大量额外的符号可能导致编译时间增加。
尽管完全展开命名空间存在命名冲突的缺点,但是有一些命名空间中的内容是我们常用的,我们可以采用指定访问的方法访问常用的内容:
//方法一
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int i = 0;
std::cin >> i;
cout << "xxxx" << endl;
cout << "xxxx" << endl;
return 0;
}
//方法二
#include <iostream>
int main()
{
int i = 0;
std::cin >> i;
std::cout << "xxxx" << std::endl;
std::cout << "xxxx" << std::endl;
return 0;
}
iostream与std的关系
iostream:指的是输入输出流(input/output stream),包括了处理输入和输出数据流的类和函数。例如
cin
,cout
,cerr
,clog
等都属于 iostream 库中定义的对象。std:代表 C++ 标准库中定义的所有内容所在命名空间。C++ 标准库提供了广泛且功能强大的类、函数和算法,在编写 C++ 程序时经常会用到这些标准库中提供的元素。
io
包含了与 I/O 相关联的部分内容(学生名单),而内容位于 std 命名空间内(特定学生)
5、可以将同一个函数放在不同的命名空间中使用
#include <iostream>
namespace N
{
int Add(int left, int right)
{
return left + right;
}
}
namespace M
{
int Add(int left, int right)
{
return left + right;
}
}
using namespace N;
int main()
{
printf("%d\n",N::Add(10, 20));
printf("%d\n",M::Add(10, 20));
return 0;
}
6、可将同一命名空间中的两个相同函数再放入两个不同的命名空间中(命名空间的嵌套)
#include <iostream>
namespace N
{
namespace a
{
int Add(int left, int right)
{
return left + right;
}
}
namespace b
{
int Add(int left, int right)
{
return left + right;
}
}
}
using namespace N;
int main()
{
printf("%d\n",N::a::Add(10, 20)); //注意这里的调用方式!!
printf("%d\n",N::b::Add(10, 20)); //注意这里的调用方式!!
return 0;
}
小补充(二)
命名空间域就相当于一个被设置了访问权限的文件,一般情况下我们在使用命名空间域中的内容时的形式是命名空间域::内容名,如果我们想直接用命名空间中的内容就会报错。而using的作用就相当于在使用之前打开该“文件”的全部或某个内容的权限,即在使用前以using 命名空间::内容名的形式获得相应的权限:
#include <iostream>
namespace N
{
int a = 10;
int b = 20;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
using N::b;
int main()
{
printf("%d\n", N::a);
printf("%d\n", b);
return 0;
}
c++的关键字
~over~
原文地址:https://blog.csdn.net/m0_73975164/article/details/136264568
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!