详细了解C++中的namespace命名空间

键盘敲烂,月薪过万,同学们,加油呀!

目录

键盘敲烂,月薪过万,同学们,加油呀!

一、命名空间的理解

二、::作用域运算符

三、命名空间(namespace)

3.1、namespace的由来

3.2、命名空间使用语法

3.3、using声明

3.4、using编译指令


一、命名空间的理解

同学们好!今天王老师来带大家了解C++中的命名空间(namespace)的一个概念。首先要了解什么是命名空间,这个大家就可以把它理解成一个工具箱,如下图:

众所周知,我们C++一般用在大型项目中,现在假设我们一共有张三,李四,王五 三个人完成一个大型项目, 因为项目太大了,所以我们在创建变量的时候就有很大的概率会造成变量名相同的一个问题,这个时候就会发生命名冲突的一个问题了,这个时候怎么办呢?这时我们就可以用到C++中的命名空间了,这个就像把我们所创建好的东西放入一个工具箱中,但是这个工具箱有好多个,每个工具箱中有个别工具是相同的(外貌相同,并不是同一个),这个时候我们需要用到哪个工具箱中的工具我们就去哪个工具箱中拿,这样就能解决命名冲突的一个问题了,这也是命名空间最大的一个用处。

比如上图中,我们如果需要用到A 空间中的a 我们就去A 中拿,要用到B 中的a 我们就去B中拿,这样编译器就不会不知道我要用的这个变量是来自于哪里了。

二、::作用域运算符

在正式了解命名空间之前我们还需要了解::作用域运算符。

通常情况下,如果有两个同名变量,一个全局变量,一个局部变量,那么局部变量在其作用域范围内有更高的优先级,它将屏蔽全局变量。

如下代码:

cpp 复制代码
int a = 10;
void fun(void)
{
    int a = 20;
    cout<<a<<endl;    
}

程序的输出结果是:

a = 20

在这个fun函数中,cout输出语句使用的变量a 是fun函数中内部定义的局部变量a ,因此输出的结果为局部变量a 的值。在C语言中,我们无法解决这个问题,无法在fun函数中访问到全局变量a,但是在C++中我们可以用作用域运算符解决这个变量重名问题。

代码如下:

cpp 复制代码
//全局变量
int a = 10;
//1. 局部变量和全局变量同名
void test(){
int a = 20;
//打印局部变量 a
cout << "局部变量 a:" << a << endl;
//打印全局变量 a
cout << "全局变量 a:" << ::a << endl;
}

从这个例子可以看出,作用域运算符可以解决局部变量与全局变量的重名问题,即在局部变量的作用域中,可用::对被屏蔽的同名的全局变量进行访问。

三、命名空间(namespace)

3.1、namespace的由来

在C++中,我们在好多地方都需要命名,比如说结构体、常量、变量、函数、枚举、类和对象等等,我们都需要去给它们取个名字。工程越大,名称互相冲突的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突,为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入了关键字namespace(命名空间),可以更好地控制标识符的作用域

3.2、命名空间使用语法

创建一个命名空间:

cpp 复制代码
namespace A{
    int a = 10;
}

namespace B{
    int a = 20;
}

void test(){
    cout<<"A::a"<<A::a<<endl;
    cout<<"B::a"<<B::a<<endl;
}

命名空间只能全局范围内定义(以下写法错误)

cpp 复制代码
//错误写法
void test(){
    namespace A{
        int a = 10;
    }
    cout<<"A::a"<<A::a<<endl;
}

命名空间可以嵌套命名空间

cpp 复制代码
namespace A{
    int a = 10;
    namespace B{
        int a = 20;
    }
}

void test(){
    cout<<"A::a"<<A::a<<endl;
    cout<<"A::B::a"<<A::B::a<<endl;
}

命名空间是开放的,即可以随时把新的成员加入已有的命名空间中

cpp 复制代码
namespace A {
    int a = 100;
    int b = 200;
}
//将c添加到已有的命名空间A中
namespace A {
    int c = 300;
}

void test04()
{
    cout<<"A中a = "<<A::a<<endl;//100
    cout<<"A中c = "<<A::c<<endl;//200
}

函数的声明和实现可以分离

cpp 复制代码
namespace A {
    int a=100;//变量

    void func();
}

void A::func()//成员函数 在外部定义的时候 记得加作用域
{
    //访问命名空间的数据不用加作用域
    cout<<"func遍历a = "<<a<<endl;
}

无名的命名空间,意味着命名空间中的标识符只能在本文件中访问,相当于给这个标识符加上了static,使得其可以作为内部连接(了解)

cpp 复制代码
namespace{
    int a = 10;
    void func(){ cout << "hello namespace" << endl; }
}
void test(){
    cout << "a : " << a << endl;
    func();
}

命名空间取别名(了解)

cpp 复制代码
namespace veryLongName{
    int a = 10;
    void func(){ cout << "hello namespace" << endl; }
}
void test(){
    namespace shortName = veryLongName;
    cout << "veryLongName::a : " << shortName::a << endl;
    veryLongName::func();
    shortName::func();
}

3.3、using声明

using声明可以使得指定的标识符可用

cpp 复制代码
namespace A{
    int paramA = 20;
    int paramB = 30;
    void funcA(){ cout << "hello funcA" << endl; }
    void funcB(){ cout << "hello funcA" << endl; }
}
void test(){
    //1. 通过命名空间域运算符
    cout << A::paramA << endl;
    A::funcA();
    //2. using 声明
    using A::paramA;
    using A::funcA;
    cout << paramA << endl;
    //cout << paramB << endl; //不可直接访问
    funcA();
    //3. 同名冲突
    //int paramA = 20; //相同作用域注意同名冲突
}

using声明碰到函数重载

cpp 复制代码
namespace A{
    void func(){}
    void func(int x){}
    int func(int x,int y){}
}
void test(){
    using A::func;
    func();
    func(10);
    func(10, 20);
}

如果命名空间包含一组用相同名字重载的函数,using声明就声明了这个重载函数的所有集合

3.4、using编译指令

using编译指令使整个空间标识符可用

cpp 复制代码
namespace A{
    int paramA = 20;
    int paramB = 30;
    void funcA(){ cout << "hello funcA" << endl; }
    void funcB(){ cout << "hello funcB" << endl; }
}
void test01(){
    using namespace A;
    cout << paramA << endl;
    cout << paramB << endl;
    funcA();
    funcB();
    //不会产生二义性
    int paramA = 30;
    cout << paramA << endl;
}

namespace B{
    int paramA = 20;
    int paramB = 30;
    void funcA(){ cout << "hello funcA" << endl; }
    void funcB(){ cout << "hello funcB" << endl; }
}
void test02(){
    using namespace A;
    using namespace B;
    //二义性产生,不知道调用 A 还是 B 的 paramA
    //cout << paramA << endl;
}
相关推荐
ぃ扶摇ぅ4 分钟前
Windows系统编程(三)进程与线程二
c++·windows
简单.is.good10 分钟前
【测试】接口测试与接口自动化
开发语言·python
Yvemil729 分钟前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的30 分钟前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节
我是陈泽1 小时前
一行 Python 代码能实现什么丧心病狂的功能?圣诞树源代码
开发语言·python·程序员·编程·python教程·python学习·python教学
Mr.Z.4111 小时前
【历年CSP-S复赛第一题】暴力解法与正解合集(2019-2022)
c++
优雅的小武先生1 小时前
QT中的按钮控件和comboBox控件和spinBox控件无法点击的bug
开发语言·qt·bug
Death2001 小时前
使用Qt进行TCP和UDP网络编程
网络·c++·qt·tcp/ip
虽千万人 吾往矣1 小时前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
创作小达人1 小时前
家政服务|基于springBoot的家政服务平台设计与实现(附项目源码+论文+数据库)
开发语言·python