本文主要介绍C++语言中的命名空间(namespace)的相关知识。
1. 概述
1.1 why
这里首先讲述为什么需要命名空间。
假设这样一种情况,当一个班上有两个名叫 liitdar 的学生时,为了在点名的时候能够明确区分他们,让他们知道确实是需要他进行回答(而不是另外一个liitdar),我们在使用名字 liitdar 的同时,还需要使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等(比如 lianmeng 的 liitdar ,或者 buluo 的 liitdar )。
上述假设的情况同样也会出现在 C++ 应用程序中。例如,我们编写了一个名为 findsomeone() 的函数,在另一个可用的库(可能是别人写的,也可能是自己写的)中也存在一个相同的函数 findsomeone()。此时,我们在调用函数 findsomeone() 时,编译器就无法判断出到底应该执行哪一个 findsomeone() 函数。
为了解决上述问题,C++ 引入了命名空间(namespace)的概念,命名空间可作为附加信息,来区分不同库中相同名称的函数、类、变量等。使用了命名空间也就定义了上下文。从本质上讲,命名空间的作用就是定义了一个范围。
2. 使用方法
这里讲述命名空间的使用方法。
2.1 命名空间的定义
命名空间的定义需要使用关键字 namespace, namespace 后跟命名空间的名称,如下所示:
namespace namespace_name { // 详细代码 }
2.2 命名空间的调用
为了调用命名空间中定义的函数(或类、变量等),需要在该函数前面加上命名空间的名称,如下所示:
namespace_name::fun();
2.3 命名空间的简单示例
下面的代码展示了命名空间的简单使用方法:
#include <iostream> using namespace std; // 命名空间 FirstNamespace namespace FirstNamespace { void func() { cout << "this is FirstNamespace print." << endl; } } // 命名空间 SecondNamespace namespace SecondNamespace { void func(){ cout << "this is SecondNamespace print." << endl; } } int main() { // 调用命名空间 FirstNamespace 中的函数 FirstNamespace::func(); return 0; }
编译并执行上述代码,可得到如下结果:
2.4 using 指令
在上面的示例代码中,我们是通过 namespace_name::fun(); 方式使用的命名空间。事实上,我们也可以使用如下的 using 指令调用命名空间中的内容(如函数、变量等):
using namespace namespace_name;
当我们进行了上面的 using 指令声明后,在使用命名空间中的内容时就可以不必在该内容的前面加上命名空间的名称了,using 指令会告诉编译器,后续的代码将使用 using 指令指定的命名空间 namespace_name 中的内容。
所以,前面的代码示例也可编写为如下的样式:
#include <iostream> using namespace std; // 命名空间 FirstNamespace namespace FirstNamespace { void func() { cout << "this is FirstNamespace print." << endl; } } // 命名空间 SecondNamespace namespace SecondNamespace { void func(){ cout << "this is SecondNamespace print." << endl; } } using namespace FirstNamespace; int main() { // 调用命名空间 FirstNamespace 中的函数 func(); return 0; }
上述代码使用了 using 指令,执行结果与前面的示例代码相同。
此外,using 指令也可以用来指定命名空间中的特定内容。例如,如果只想要使用 std 命名空间中的 cout ,则可以使用如下的语句:
using std::cout;
这样,在随后的代码中,使用到 cout 时就会直接使用命名空间 std 中的 cout 了(而不用加上命名空间名称 std 作为前缀),但是如果需要使用 std 命名空间中的其他内容,则仍然需要加上命名空间名称 std 作为前缀,示例代码如下:
#include <iostream> using std::cout; int main() { cout << "std::endl is used with namespace std!" << std::endl; return 0; }
编译并执行上述代码,结果如下:
说明: using 指令引入的命名空间的名称遵循正常的(名称)范围规则。命名空间名称从声明 using 指令开始生效,直到该范围结束时失效。
2.4 命名空间的分散性
同一个命名空间的内容可以定义在几个不同的部分中,因此命名空间可以是由几个单独定义部分组成的。一个命名空间的各个组成部分可以分散在多个文件中。
示例代码如下:
#include <iostream> using namespace std; // 命名空间 FirstNamespace namespace FirstNamespace { void func() { cout << "this is FirstNamespace print." << endl; } } // 在另外一个位置,再次定义命名空间 FirstNamespace namespace FirstNamespace { void func1() { cout << "this is another FirstNamespace print." << endl; } } int main() { // 调用新定义的命名空间 FirstNamespace 中的函数 FirstNamespace::func1(); return 0; }
编译并执行上述代码,结果如下:
2.5 命名空间的嵌套
命名空间可以嵌套,可以在一个命名空间中定义另一个命名空间,如下所示:
namespace NamespaceName1 { // 详细代码 namespace NamespaceName2 { // 详细代码 } }
可以通过使用域运算符 :: 来访问嵌套的命名空间中的成员,如下:
// 访问 NamespaceName2 中的成员 using namespace NamespaceName1::NamespaceName2;
示例代码如下:
#include <iostream> using namespace std; // 命名空间 FirstNamespace namespace FirstNamespace { void func() { cout << "this is FirstNamespace print." << endl; } // 命名空间 SecondNamespace namespace SecondNamespace { void func() { cout << "this is SecondNamespace print." << endl; } } } using namespace FirstNamespace::SecondNamespace; int main() { // 调用命名空间 SecondNamespace 中的函数 func(); return 0; }
编译并执行上述代码,结果如下: