名称空间是C++为了防止写程序时命名发送冲突而设计出来的,其实和文件夹类似,不同名称空间下的名称可以相同。
接触过C++的人都应该对using namespace std
很熟悉,这就是大家最常见的名称空间应用,叫做using编译指令,其中std
是一个名称空间的名字。
C++提供了两种机制来简化对名称空间中名称的使用:
- using声明(例如:using std::cout)
- using编译指令(例如:using namespace std)
先我们来了解声明是名称空间,看代码
#include <iostream>
namespace nsp {
int a = 0;
void hello()
{
std::cout << "Hello!" << std::endl;
}
}
int main()
{
std::cout << nsp::a << std::endl;
nsp::hello();
}
代码中定义了名称空间 nsp,其中包含两个名称 a 和 hello,如果不使用 using 命令,那就只能用域解析运算符::
来进行使用了。
名称空间相当于将一些名称打包,然后给这个包取个名字,通过名称空间的名字和域解析运算符::
就可以使用里面的名称了
使用 using 声明,就是把里面的一个名称单独取出来使用,如:`using nsp::hello',要记住函数名称后面不能加括号
使用 using 编译指令,就是把包给解开,使得所有名称都可以使用,如:'using namespace nsp'
使用 using 指令后,名称的可用范围时从使用处起,到该作用域结束为止
例如如果是在函数里用,就是从使用位置开始到函数结束的位置,在这个范围里可以直接使用释放出来的名称
::
还可以用于访问被局部变量覆盖了的全局变量,如test.cpp中代码,其中::x
表示的就是全局duoble型变量 x:
#include <iostream>
double x = 27.0;
void test(int a)
{
int x = a;
{
using std::cout;
char x = 'Q';
cout << "最内层x = " << x << "
"
<< "全局::x = " << ::x << std::endl;
}
using std::endl;
std::cout << "中间层x = " << x << '
' << endl;
}
下面是文件main.cpp的内容:
extern void test(int x); // extern 可以省略,不省略的好处是可以明确指出这是在外部文件定义的函数
namespace nsp {
int a = 7;
}
int main()
{
using namespace nsp;
test(a); // a 为 7
int a = 9;
test(a); // a 为 9
}
注意:使用 using 声明后,不可在同一级别的作用域里再次声明一样的名称,因为 using 声明也相当于声明,而 C++ 不允许在同一文件中重复声明,不过可以在不同级别的作用域里再次声明,一层花括号就是更深一层的作用域。不过 using 编译指令就没有这个限制了,你还是可以重复声明一次相同的名称。
使用名称空间还需要注意:
- 名称空间可以嵌套,但不可以在代码块中,例如在函数中定义名称空间
- 同一名称空间可分布在不同的文件中,也可以在同一文件的不同位置
- 要使用名称空间中在其他文件里的变量或者函数,需要在本文件的名称空间中声明为外部变量,函数也一样
如下面代码:
// test.cpp
#include <iostream>
namespace nsp
{
double x = 27.0;
void test(int a)
{
using namespace std;
cout << a << endl;
}
}
// main.cpp
namespace nsp {
int a = 7;
extern double x; // 必须加 extern 否则会报错
extern void test(int); // 可省略 extern
}
namespace nsp {
int b = 8;
}
int main()
{
using namespace nsp;
test(a); // a 为 7
test(b); // b 为 8
int a = 9;
test(a); // a 为 9
test(x); // x 为 27
}
下面是使用头文件的情况,一般在项目中都会把声明放到头文件中,然后再用同名称的.cpp文件来进行实现
// test.h
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
namespace TEST
{
const double x = 27.0; // 温馨提示:头文件中不要有变量
void test(int);
}
#endif // TEST_H_INCLUDED
// test.cpp
#include <iostream>
#include "test.h"
namespace TEST
{
void test(int a)
{
using namespace std;
cout << a << endl;
}
}
// main.cpp
#include "test.h"
namespace TEST {
int a = 7;
}
namespace TEST {
int b = 8;
}
int main()
{
using namespace TEST;
test(a); // a 为 7
test(b); // b 为 8
int a = 9;
test(a); // a 为 9
test(x); // x 为 27
}
预编译指令#include "test.h"
的作用其实就是将 test.h 文件中的内容替换掉这一行。
我是七进制,一个被编程耽误的吉他手