目录
前言
为什么c++要在c的基础上衍生出命名空间呢?命名空间究竟该怎么使用呢?让我们一起来探讨一下。
一、::冒号作用域运算符
在正式探讨命名空间之前,我们首先了解一下::冒号作用域运算符。::冒号作用域运算符用来指定哪个作用域。下面用代码演示一下基本用法。
1.::前面不加任何字母代表全局作用域下的某个数据。
可以看到,同样是a,当我们在a的前面加上::冒号作用域运算符,编译器就会在全局范围内查找a,由于我未在全局范围内定义a,所以编译器报错,显示“ 全局范围内没有'a' ”。
2.::前面加上一串字母,代表该作用域下的数据。
例如:A::B代表的是A作用域下的B。
此知识将在后面的命名空间里面再次提到。
二、命名空间
为什么我们需要引入命名空间的概念呢?假想一下,我们有一座庞大的学校,但是学校的内部组织却是混乱的,没有设立班级,没有设立行政部门等等。有一天,我们的校长心血来潮,想找我们学校名叫张三的同学谈话,那么问题来了,如果名叫张三的同学不只有一位,那么校长究竟想找的人到底是谁呢?于是我们开始设立班级、行政部门等等,这天,校长终于找到了张三。我们的校长想找的是六年级三班的张三。
事实上,命名空间正是为了解决上面的问题而存在的。当我们在编写程序时,随着代码的长度增长,我们很可能写出多个重名的函数或者变量,为了防止混乱,C++中便加入了命名空间来划分各间“教室”。
知道了命名空间为什么而存在,下面我们将具体地讨论命名空间的用法。
1.namespace
namespace,我们将其分开来看,前半部分name翻译过来就是名字、命名的意思,后半部分space翻译过来就是空间的意思。前面讨论的命名空间指的便是这个关键字。
namespace的基本用法如下:
- 必须定义在全局范围内
- 命名空间内可以存放变量、函数、类、结构体
#include<iostream>
using namespace std;
//在全局范围内定义命名空间
namespace test {
//变量
int a = 4;
//类
class point {
int name;
int age;
};
//函数
void test() {
cout << "你好,优快云!" << endl;
};
//结构体
struct Studnet {
char* name;
int age;
};
};
int main() {
return 0;
}
- 允许重名,重名相当于合并
#include<iostream>
using namespace std;
//在全局范围内定义命名空间
namespace test {
int a = 4;
};
//与上面重名的命名空间
namespace test {
int b = 5;
};
int main() {
//可以看到,此处再次出现了上面提到的A::B的情况
//这里表示的是在命名空间test作用域下的a和b
cout << test::a <<" " << test::b << endl;//运行结果为4 5
return 0;
}
- 命名空间可以嵌套命名空间
#include<iostream>
using namespace std;
namespace a {
int m = 1;
//嵌套一个命名空间b
namespace b {
int n = 4;
};
}
int main() {
//表示输出a作用域下的b作用域下的n
cout << a::b::n;
return 0;
}
- 命名空间可以取别名
#include<iostream>
using namespace std;
namespace a {
int n = 3;
}
namespace b = a;
int main() {
//输出值一样
cout << a::n << endl;//输出为3
cout << b::n << endl;//输出为3
//修改作用域下n的值再次输出
b::n = 1;
cout << a::n << endl;//输出为1
cout << b::n << endl;//输出为1
/*可以看到,当b作用域下的n修改时,
a作用域下的n也会相应修改,可以推测a与b指向的是
同一块内存空间,相当于C++中的引用*/
return 0;
}
- 命名空间可以没有名字,没有名字相当于给命名空间内所用成员加上static修饰
#include<iostream>
using namespace std;
namespace {
int n = 3;//相当于 static int a = 3;
}
int main() {
cout << n;//输出为3
//可以看到,n前面并没有指定作用域,但是还是正常输出了。
return 0;
}
- 命名空间中的函数可以先声明,在外部定义,定义时需加上命名空间作用域
#include<iostream>
using namespace std;
namespace a {
//声明
void w();
}
void w() {
cout << "你好世界!" << endl;
}
//定义
void a::w() {
cout << "你好,优快云 !" << endl;
}
int main() {
w();
a::w();
return 0;
}
小结:以上便是namespace的一些基础的用法,我们再来回顾一下。
- 必须定义在全局范围内。
- 命名空间内可以存放变量、函数、类、结构体。
- 允许重名,重名相当于合并。
- 命名空间可以嵌套命名空间。
- 命名空间可以取别名。
- 命名空间可以没有名字,没有名字相当于给命名空间内所用成员加上static修饰。
- 命名空间中的函数可以先声明,在外部定义,定义时需加上命名空间作用域。
2.using关键字
一般来说,命名空间可以配合using来使用,让代码看起来更加简洁与舒畅。using的基本用法如下:
#include<iostream>
using namespace std;
namespace a {
int w = 1;
int b = 2;
}
//用法一 指定某命名空间内特定的数据可用
void test01() {
using a::w;
cout << w << endl;//using 指定了使用a命名空间内的w,所以此处的w便是a::w
//cout << b;//此处没有用 using 指定 a 命名空间内的 b ,所以会报错
}
//用法二 使用整个命名空间
void test02() {
using namespace a;//直接使用整个命名空间a,a中的所有数据都可以在这里使用
cout << w << endl;
cout << b << endl;
}
int main() {
test01();
test02();
return 0;
}
此外,在使用using时,我们还有两点需要注意的地方,一是注意局部变量与命名空间中的变量的冲突,二是注意命名空间之间的重名冲突。
- 局部边量与命名空间的变量发生冲突时,优先使用局部变量
#include<iostream>
using namespace std;
namespace a {
int w = 1;
int b = 2;
}
/*局部变量与命名空间中的冲突*/
void test01() {
using namespace a;//此处使用了命名空间 a
int w = 8;
cout << w;//此处输出为8
}
int main() {
test01();
return 0;
}
另外,如果using a::w与局部变量w冲突,将会报错。
- 注意命名空间之间的重名冲突
我们现在应该可以明白,C++中我们一上来就写的using namespace std;是什么意思了,此处的意思大概就是使用std这个标准的命名空间。在std中,有cout,endl和cin,我们可以以此为依据,来看看命名空间之间的重名冲突。
可以看到,编译器给我们报错了。可以将cout改为std::cout来解决这个问题。
小结:using有两个基本的使用点和两个注意点。
总结
本文介绍了C++中命名空间存在的原因以及其基本的用法,如果您还觉得不错的话,可以点个免费的小赞支持一下,让我们共同进步吧!