C++命名空间(namespace)详解(附带实例)
一个应用程序中可能存在多个文件,有时会存在同名问题,从而导致程序链接错误。使用命名空间是消除命名冲突的最佳方式。简而言之,命名空间就是一个命名的范围区域,程序员在这个特定范围内创建的所有标识符都是唯一的。
例如,下面的代码中定义了一个命名空间 MyName,其中定义了两个整型变量 iInt1 和 iInt2:
引用命名空间中的成员需要使用域限定符 ::。例如,引用 MyName 命名空间中的 iInt1 变量,代码如下:
【实例】使用 namespace 关键字定义两个命名空间 MyName1 和 MyName2。代码如下:
还有一种引用命名空间中成员的方法,就是使用 using namespace 语句,一般形式如下:
例如,在源程序中包含 MyName 命名空间,代码如下:
【实例】使用 using namespace 语句将命名空间包含在程序中,引用命名空间中的变量。
注意,如果定义了多个命名空间且存在相同的标识符,使用 using namespace 语句引用成员时就会产生歧义,这时最好使用域限定符进行引用。
例如,在头文件中声明命名空间函数,代码如下:
在源文件中定义函数,代码如下:
注意,在源文件中定义函数时,要使用域限定符 ::,并将命名空间名作为前缀,表明实现的是命名空间中定义的函数。否则,将定义一个全局函数。
【实例】将命名空间的定义放在头文件中,将命名空间中有关成员的定义放在源文件中。
1) Detach.h:
2) Detach.cpp:
如果再在 Detach.cpp 源文件中定义一个 Output 命名空间:
也可以使用 using namespace 命令引用嵌套的 MyName 命名空间。例如:
C++命名空间的定义
定义命名空间需要使用 namespace 关键字,具体格式如下:namespace 名称 { 常量、变量、函数等对象的定义 }
例如,下面的代码中定义了一个命名空间 MyName,其中定义了两个整型变量 iInt1 和 iInt2:
namespace MyName { int iInt1 = 10; int iInt2 = 20; }
引用命名空间中的成员需要使用域限定符 ::。例如,引用 MyName 命名空间中的 iInt1 变量,代码如下:
MyName::iInt1 = 30;
【实例】使用 namespace 关键字定义两个命名空间 MyName1 和 MyName2。代码如下:
#include <iostream> using namespace std; namespace MyName1 // 定义命名空间MyName1,包含变量iValue { int iValue = 10; } namespace MyName2 // 定义命名空间MyName2,包含变量iValue { int iValue = 20; } int iValue = 30; // 定义全局变量iValue int main() { cout << MyName1::iValue << endl; // 引用MyName1命名空间中的iValue cout << MyName2::iValue << endl; // 引用MyName2命名空间中的iValue cout << iValue << endl; // 输出全局变量iValue return 0; }程序运行结果为:
10
20
30
还有一种引用命名空间中成员的方法,就是使用 using namespace 语句,一般形式如下:
using namespace 命名空间名称;
例如,在源程序中包含 MyName 命名空间,代码如下:
using namespace MyName; iInt=30;使用 using namespace 语句时,可以直接引用空间中的成员,不必使用域限定符“::”。
【实例】使用 using namespace 语句将命名空间包含在程序中,引用命名空间中的变量。
#include <iostream> using namespace std; namespace MyName // 定义命名空间MyName { int iValue = 10; // 定义整型变量 } using namespace MyName; // 使用命名空间MyName int main() { cout << iValue << endl; // 直接引用MyName命名空间中的iValue,不必使用域限定符“::” return 0; }程序运行结果为:
10
上述代码中使用 using namespace 语句和 MyName 命名空间,这样 main() 函数中的 iValue 指的就是 MyName 命名空间中的 iValue。注意,如果定义了多个命名空间且存在相同的标识符,使用 using namespace 语句引用成员时就会产生歧义,这时最好使用域限定符进行引用。
C++在多个文件中定义命名空间
定义命名空间时,通常在头文件中声明命名空间中的函数,在源文件中定义命名空间中的函数,将程序的声明部分与实现部分分开。例如,在头文件中声明命名空间函数,代码如下:
namespace Output { void Demo(); // 声明函数 }
在源文件中定义函数,代码如下:
void Output::Demo() // 定义函数 { cout << "This is a function!\n"; }
注意,在源文件中定义函数时,要使用域限定符 ::,并将命名空间名作为前缀,表明实现的是命名空间中定义的函数。否则,将定义一个全局函数。
【实例】将命名空间的定义放在头文件中,将命名空间中有关成员的定义放在源文件中。
1) Detach.h:
namespace Output // 定义Output命名空间 { void Demo(); // 声明Demo()函数 }
2) Detach.cpp:
#include <iostream> #include "Detach.h" using namespace std; void Output::Demo() // 定义Output命名空间下的Demo()函数 { cout << "This is a function!\n"; } int main() { Output::Demo(); // 调用Output命名空间下的Demo()函数 return 0; }程序运行结果为:
This is a function!
如果再在 Detach.cpp 源文件中定义一个 Output 命名空间:
namespace Output // 定义Output命名空间 { void show() // 定义show()函数 { cout << "This is show function" << endl; } }此时 Output 命名空间的内容为两个文件中 Output 命名空间内容的总和。如果读者想在 Detach.cpp 文件的 Output 命名空间中再定义一个 Demo() 函数,编译器将提示错误,因为已经存在 Demo() 函数了。
C++定义嵌套的命名空间
命名空间可以嵌套定义,例如:namespace Output // 定义命名空间Output { void Show() // 定义函数Show(),属于命名空间Output { cout << "Output's function!" << endl; } namespace MyName // 嵌套定义命名空间MyName { void Demo() // 定义函数Demo(),属于命名空间MyName { cout << "MyName's function!" << endl; } } }上述代码中,在 Output 命名空间中嵌套定义了 MyName 命名空间。如果要访问命名空间中的对象,则需要使用域限定符“::”,将外层、内层的命名空间都作为前缀。例如:
Output::Show(); // 调用Output命名空间中的Show()函数 Output::MyName::Demo(); // 调用MyName命名空间中的Demo()函数
也可以使用 using namespace 命令引用嵌套的 MyName 命名空间。例如:
using namespace Output::MyName; // 引用嵌套的MyName命名空间 Demo(); // 调用MyName命名空间中的Demo()函数上述代码中,“using namespace Output::MyName;”语句只引用了嵌套在 Output 命名空间中的 MyName 命名空间,并没有引用 Output 命名空间,因此试图访问 Output 命名空间中定义的对象将是非法操作。例如:
using namespace Output::MyName; // 引用嵌套的MyName命名空间 Show(); // 错误,无法访问Output命名空间中的Show()函数