一.为什么要命名空间
我们知道在一个学校,一个班级难免会存在两个人的名字是相同的,那么我们区分他们的话,那就不能只仅仅根据名字了,我们可能还需要加入其他的条件,如性别,年龄…!
同样的,我们在c++编写时,可能我们正在编写一些具有名为geqian()函数的代码,并且还有另一个可用的库,它也具有相同的geqian()函数。现在编译器无法知道您在代码中引用的geqian()函数的哪个版本。那么编译器就会报错!
eg:
#include<iostream>
#include <stdlib.h>
int rand = 1;
int main()
{
printf("%d\n", rand);
return 0;
}
当我们运行时,会报错,说rand重定义了,以前定义是函数,这是为啥呢?
这是因为我们在C语言中,stdlib中有一个rand()的库函数,与我们要使用的这个变量rand相冲突了,所以编译器才会报错!
那么,我们要怎么解决这个问题呢?
这就使用到了我们c++中命名空间,使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的!
二.命名空间的定义:
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。
1.命名空间将全局作用域分成不同的部分;
2.不同命名空间中的标识符可以同名而不会发生冲突;
3.命名空间可以发生嵌套;
4.全局作用域也叫默认命名空间;
namespace geqian //geqian是命名空间的名字
{
//命名空间中可以定义变量/函数/结构体类型
int rand = 1;
int add(int a, int b)
{
return a + b;
}
struct Stu
{
char name;
int age;
};
}
//命名空间可以嵌套
namespace geqian
{
int a;
int b;
int mul(int a, int b)
{
return a * b;
}
namespace geqian10
{
int c;
int d;
int sub(int a, int b)
{
return a - b;
}
}
}
并且在同一个工程中允许存在多个相同名称的命名空间,编译器最终会合并成同一个命名空间中。
eg:我再test.h中再定义一个geqian,那么在test.c和test.h中两个geqian就会合并成一个。
**注意:**一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
三.命名空间的使用:
那么,命名空间到底如何使用呢?
命名空间的使用有三种方式:
一:加命名空间名称及作用域限定符
#include<iostream>
namespace geqian
{
int rand = 1;
}
int main()
{
printf("%d\n", geqian::rand);
return 0;
}
这里的geqian就是我们所说的命名空间名称,而::就是作用域限定符
二:使用using将命名空间中某个成员引入
#include<iostream>
namespace geqian
{
//int rand = 1;
int rand1 = 2;
}
using geqian::rand1;
int main()
{
//printf("%d\n", geqian::rand);
printf("%d\n", rand1);
return 0;
}
三:使用using namespace 命名空间名称 引入
#include<iostream>
namespace geqian
{
int rand = 1;
int rand1 = 2;
}
using namespace geqian;
int main()
{
printf("%d\n", geqian::rand);
printf("%d\n", rand1);
return 0;
}
汇总以上eg:
#include <iostream>
namespace geqian1
{
int a = 10;
}
namespace geqian2
{
int a = 20;
namespace geqian3 //嵌套命名空间
{
struct P //嵌套命名空间
{
int x;
int y;
};
}
}
int main()
{
using namespace geqian1; //使用using namespace 整个命名空间名称引入
using geqian2::geqian3::P; //使用嵌套的命名空间
printf("%d\n", a);
printf("%d\n", geqian2::a); //使用命名空间中的变量
P p = { 30, 40};
printf("%d\n", p.x);
printf("%d\n", p.y);
return 0;
}
运行结果:
四:命名空间访问顺序:
那么到目前为止,我们已经get了,局部域,全局域,命名空间域,那在我们的代码中,这几者之间的访问顺序是怎样的?
先上结论:
局部域->全局域 -> 展开了命名空间域 or 指定访问命名空间域
下面,我们用代码一一验证
首先,毫无疑问的是局部域肯定是优先我们全局域的,因为我们的局部变量的优先级高于全局变量的优先级!
那如果我们就是想访问全局变量的,我们可以在访问对象前加::,这样我们访问的就是全局变量
#include <iostream>
int rand = 1;
int main()
{
int rand = 2;
printf("%d\n", ::rand);
return 0;
}
在下面这种情况,不存在全局变量,我们也可以把命名空间域当作全局变量一样看待:
#include <iostream>
namespace geqian
{
int a = 2;
}
using namespace geqian;//展开命名空间域
int main()
{
printf("%d\n", a);
return 0;
}
如果,我们在命名空间域中,我们想指定一个特殊的变量或者函数,那么我们可以使用using 命名空间名::变量/函数名。
#include <iostream>
namespace geqian
{
int a = 2;
int add(int x, int y)
{
return x + y;
}
}
using geqian::add;
int main()
{
//printf("%d\n", a); 这个就会发生报错
printf("%d\n", add(3,4));
return 0;
}
运行结果:
本篇博客的内容【NameSpace --命名空间的使用】到此结束。
若对你有些许帮助,可以点赞、关注、评论支持下博主,你的支持将是我前进路上最大的动力。
若以上内容有任何问题,欢迎在评论区指出。若对以上内容有任何不解,都可私信评论询问。
诸君,山顶见!