C++名称空间

名称空间是C++为了防止写程序时命名发送冲突而设计出来的,其实和文件夹类似,不同名称空间下的名称可以相同。
接触过C++的人都应该对using namespace std很熟悉,这就是大家最常见的名称空间应用,叫做using编译指令,其中std是一个名称空间的名字。

C++提供了两种机制来简化对名称空间中名称的使用:

  1. using声明(例如:using std::cout)
  2. 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 编译指令就没有这个限制了,你还是可以重复声明一次相同的名称。

使用名称空间还需要注意:

  1. 名称空间可以嵌套,但不可以在代码块中,例如在函数中定义名称空间
  2. 同一名称空间可分布在不同的文件中,也可以在同一文件的不同位置
  3. 要使用名称空间中在其他文件里的变量或者函数,需要在本文件的名称空间中声明为外部变量,函数也一样

如下面代码:

// 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 文件中的内容替换掉这一行。

我是七进制,一个被编程耽误的吉他手

原文地址:https://www.cnblogs.com/qijinzhi/p/cpp_namespace.html