目录
1.C语言重命名问题
我们在学习c语言的时候会不会出现定义两个名字一样的变量就会出现重定义的问题,或者我们定
义一个变量,名字与头文件中函数的名字一样,会出现重定义的问题,看一下下面代码的问题:
#include<stdio.h>
#include<stdlib.h>
int rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}
我们定义了一个变量名为rand的变量,但是stdlib.h头文件中有rand函数,stdlib.h在预处理的时候会展开,然后就会出现重定义的问题。
这个问题在c语言中叫做命名冲突问题,主要体现在程序员和库,程序员和程序员
2.域的概念
我们知道全局域和局部域,今天我们要学习的是命名空间域,我们看下面代码,第一个打印出来是0,(我们应该都知道为什么,c语言有就近原则,先去局部找,再去全局找),为什么第二个打印出来是1呢,我们这里来学习两个冒号组成的域作用限定符,当域作用限定符左边为空的时候,默认所指的就是全局域,就是去全局域找。这样可以区分开全局和局部,都可以访问。
#include<stdio.h>
int x = 1;
int main()
{
int x = 0;
printf("%d\n", x);
printf("%d\n", ::x);//::域作用限定符
return 0;
}
3.命名空间的定义
命名空间域是处理命名冲突的问题,假如我们想在全局定义两个x出来,正常来说是定义不出来的,会有重定义的问题,接下来我们用C++关键字加上域作用限定符就可以解决这类问题:
#include<stdio.h>
namespace bit1
{
int x = 1;
}
namespace bit2
{
int x = 0;
}
int main()
{
printf("%d\n", bit1::x);
printf("%d\n", bit2::x);
return 0;
}
我们这里可以用namespace关键字给两个x分别封装起来然后起不同的域名,x还是全局变量不会改变,但是我们打印的时候不能直接打印x,而是要在域作用限定符前面加上域名,指定我们去哪个域里面去找x(编译器默认会在当前局部域搜索,找不到再去全局域找,上面我们指定了就会直接去指定域搜索)
注:命名空间域的域名可以相同,但是有一点要注意,名字相同的域里面不能定义同名变量,会有重定义的问题。但是因为域可以嵌套,我们再定义两个域分装同名变量就可以解决了。
命名空间域里面不仅能定义变量,还可以定义函数和结构体。
namespace bit
{
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
bit::Add;
struct bit::Node n1;
return 0;
}
指定结构体的时候是在结构体名字的前面加指定域,可能会比较怪。
4.命名空间的使用场景
4.1:第一种场景(包含头文件问题)
队列头文件.h声明:
栈头文件.h声明:
我们可以看到上面两个头文件结构体名字一样,我们现在在test.cpp中包含这两个头文件就会出问题:
这个时候我们用命名空间域封装一下就可以解决这个问题了,如果我们命名空间域的名字相同,我们就要把重命名的结构体改一下名。因为编译器看到两个域的域名相同就会合并这两个域。所以我们保证内部不冲突,合并起来就不会有问题。
4.2:第二种场景(命名空间展开)
int main()
{
struct bit::Node n1;
struct bit::Node n2;
struct bit::Node n3;
return 0;
}
假如我们封装了命名空间域,我们要定义几个结构体变量会很麻烦(如上代码),这个时候我们就可以展开命名空间,什么意思呢,因为命名空间域本来就是全局变量封装起来的,现在展开了,就又变成了全局变量(如下代码,可以指定域,也可以不指定域)
注:不要把命名空间展开和头文件展开弄混了,头文件展开是.cpp文件包含了,然后在预处理阶段会把这个头文件的内容拷贝到.cpp(假如这个头文件里有命名空间域,我们不指定还是访问不到,如果命名空间展开了,我们就不用指定了)
#include"List.h"
#include"Queue.h"
using namespace bit;//展开命名空间
int main()
{
struct Node n1;
struct bit::Node n2;
struct bit::Node n3;
return 0;
}
5.初步理解C++打印
学习完命名空间我们就很好理解下面的cout和endl
我们包了头文件为什么用不了cout和endl,我们可能看到过头文件下面有一句using namespace std;前面我们都知道,就是展开命名空间,这里的std是所有C++库的命名空间,所有我们这里包含了头文件没有用,因为我们只是把头文件内容拷贝过来,我们还要指定命名空间
三种解决方法:
1.指定命名空间
#include<iostream>
int main()
{
std::cout << "hello world" << std::endl;
return 0;
}
2.展开命名空间
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;
return 0;
}
注:展开命名空间是图方便的做法,实际应用中最好不要这样,可能会与别人的命名空间内容产生冲突
3.展开部分命名空间
#include<iostream>
using std::cout;
using std::endl;
int main()
{
cout << "hello world" << endl;
return 0;
}