天天看点

C++:04---命名空间(namespace)

一、概念:

  • ①类似于仓库,空间内存储代码,需要用到时调用
  • ②也为防止名字冲突提供了更加可控的机制

二、命名空间的定义

  • 定义的基本格式如下:
namespace  命名空间名
{
    //一系列声明与定义
};           

三、命名空间的注意事项

  • 命名空间定义时最后的分号可有可无
  • 只要出现在全局作用域中的声明都可置于命名空间内:类、变量定义(及其初始化)、函数声明(及其定义)、模板、其它命名空间....等
  • 命名空间可以嵌套 

四、命名空间的使用

  • 方式:先using声明命名空间,然后直接使用命名空间内代码
//例
namespace mySpace
{
    int a=1;
    void fun();//声明函数
    namespace ns //命名空间的嵌套
    {
    };
};
void mySpace::fun() //定义函数要带上命名空间作用域限定符
{
    cout<<"mySpace";
}           

命名空间的声明

//声明mySpace命名空间,空间内所有代码都可使用
using namespace mySpace;

 //声明mySpace命名空间内的fun函数,只有fun函数可供外界使用
using namespace mySpace::fun;

 //声明mySpace命名空间内的ns命名空间,只有ns命名空间可供外界使用
using namespace mySpace::ns;           

命名空间的使用

  • 使用命名空间内代码时可直接使用,也可以在前面加上命名空间名
using namespace mySpace;
int main()
{
    cout<<a;
    cout<<mySpace::a;

    fun();
    mySpace::fun();
    return 0;
}           

五、多个命名空间使用、以及作用域的关系

  • 1.多个命名空间使用时,如果变量、函数名等重名时,使用时需要加上作用域限定符
namespace ns1
{
    int a=1;
}
namespace ns2
{
    int a=2;
}
using namespace::ns1;
using namespace::ns2;

int main()
{
    cout<<a;//错误,产生二义性
    
    cout<<ns1::a;//1
    cout<<ns2::a;//2
}           
  • 2. 命名空间变量、函数等与全局变量的重名时,使用时需要加上作用域限定符
    • 全局变量的在前面加上::,命名空间的在前面加上命名空间名
namespace ns1
{
    int a=1;
}
using namespace::ns1;
int a=2;

int main()
{
    cout<<a;//错误,产生二义性
    
    cout<<::a; //打印全局变量
    cout<<ns1::a;
}           
  • 3.命名空间变量、函数等与局部变量重名时。如果不加作用域限定符,局部变量会覆盖命名空间内成员
    • 此处的作用域限定符可以直接加::,或者加上命名空间名
namespace ns1
{
    int a=1;
}
using namespace::ns1;
int main()
{
    int a=2;
    cout<<a; //2

    cout<<::a;//1
    cout<<ns1::a;//1
}           

六、未命名的命名空间

  • 1.在定义时省去命名空间名:
namespace
{
    int a=1;
    void fun();
}           
  • 2.特点:
    • 拥有静态生命周期,取代了C语言中的static,使得其在整个文件中有效,其他文件无效
    • 还可嵌套其它命名空间
    • 命名空间内的名字要与其作用域的其它名字有所区别,否则产生二义性

七、命名空间取别名

  • 方法:直接用=号取别名
namespace ns1
{
    int a=1;
};
namespace ns2=ns1;//取别名

using namespace ns2;//实质就是对ns1的声明           

八、using声明与using指示的区别

  • using声明:一条using声明一次只能引入命名空间内的一个成员,它使得程序知道我们所用的是哪个空间内的名字
  • using指示:一条using指示将命名空间内的所有成员都变的可见,声明了所有成员
namespce A
{
    int i,j;
}
using namespace A;//using指示
using A::i;//using声明
using A::j;//using声明           
  • 注意:
    • 避免使用using指示,原因:因为只要一条using指示,命名空间内的所有成员都变得可见,这会与其作用域的其它名称产生冲突,造成很严重的污染问题。并且会产生很多的二义性
    • 因此,我们建议,尽量使用using声明
//例如我们使用命名空间std的cout和cin。不要直接使用using namespace std;
#include<iostream>
using std::cout;
using std::cin;           

九、命名空间与重载

  • 1.重载与using声明
    • using声明时声明的是一个名字,而非一个特定的函数
    • 该函数的所有版本都被引入到当前作用域中
    • 注意:如果using声明的一个函数与作用域的一个函数同名且参数列表相同,将发生错误
using NS::print;//正确
using NS::print(int);//错误,不能指定参数列表           
  • 2.重载与using指示
    • using指示将空间内的所有函数都加载到重载集合中
    • 与using声明不同的是:using指示引入一个与作用域内函数名且参数列表相同的函数不会发生错误(但是我们要指明调用的是命名空间的还是当前作用域的)
namespace NS
{
    extern void print(int);
    extern void print(double);
}
void print(const std::string&);
using namespace NS;
int main()
{
    print("Hello");//调用全局函数
    print(10);//调用命名空间NS的
}           

继续阅读