首页 > 编程笔记 > C++笔记 阅读:11

C++命名空间(namespace)详解(附带实例)

一个应用程序中可能存在多个文件,有时会存在同名问题,从而导致程序链接错误。使用命名空间是消除命名冲突的最佳方式。简而言之,命名空间就是一个命名的范围区域,程序员在这个特定范围内创建的所有标识符都是唯一的。

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

上述代码中,在命名空间 MyName1 和 MyName2 中定义了同名变量 iValue,分别赋值为 10 和 20;在源文件中又定义了一个全局变量 iValue,赋值为 30;最后在 main() 函数中分别调用它们并输出显示。

还有一种引用命名空间中成员的方法,就是使用 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()函数

相关文章