设为首页收藏本站
查看: 339|回复: 3

11.《剑指C++》之从C到C++(11)

[复制链接]
  • TA的每日心情
    擦汗
    昨天 08:01
  • 签到天数: 760 天

    [LV.10]以坛为家III

    发表于 2020-6-16 09:07:47 | 显示全部楼层 |阅读模式
    本帖最后由 御天行 于 2020-6-17 08:20 编辑

    ======《剑指C++系列》:总目录======

    本讲主要介绍:命名空间
    命名空间是为了大型项目的开发,而引入的一种避免命名冲突的机制。比如:在一个大型项目里,要用到多家软件开发商提供的类库,在事先没有约定的情况下,两套类库可能存在同名函数或是全局变量而产生冲突。
    鉴于这类大型项目的开发需要,C++引入了命名空间的概念。其实这种概念在C语言中也有,只是没有被概念化。
    C语言中的命名空间
    C语言将工程的命名空间划分为,全局无名命名空间函数命名空间。全局命名空间中,不可以有重名的全局变量和函数(除非被static修饰),函数命名空间,不可以用重名的局部变量。

    如下,定义一个全局变量var,再在main函数中定义一个局部变量var,此时打印var的值,调用的是局部变量,那该如何调用全局变量var呢?
    1. #include <iostream>
    2. using namespace std;

    3. int var = 100;

    4. int main(void){

    5.     int var =150;
    6.     cout<<"var ="<<var<<endl;  //此时打印的是main中的var=150;

    7.     return 0;
    8. }
    复制代码

    我们可以做如下改进:
    ①通过指针来操作:在main函数中定义var之前,先定义全局变量var的指针,后续可以通过指针来操作全局变量var。
    ②通过域运算符::来操作。我们可以通过命名空间名+::+命名空间内成员的方式来操作重名变量。由于全局变量属于无名命名空间,因此只需通过::+命名空间内成员即可调用。
    1. #include <iostream>
    2. using namespace std;

    3. int var = 100;

    4. int main(void){

    5.     int *p = &var;    //将全局变量var的地址赋给指针p
    6.     int var =150;

    7.     cout<<"main var ="<<var<<endl;
    8.     cout<<"global var ="<<*p<<endl;  //打印p指向的值(全局变量var的值)
    9.     cout<<"global var ="<<::var<<endl;   //通过域运算符来操作

    10.     return 0;
    11. }
    复制代码

    C++在C语言的基础之上,C++首次以语法的形式,确立了全局无名命名空间的存在和使用方法(如上,通过::+命名空间内成员进行操作)。
    namespace定义
    C++语法引入namespace的本质是对全局命名空间再次划分。确切的说,是对全局的函数和变量再次进行作用域打包。
    命名空间的声明及namespace中可以包含的内容:

    命名空间的使用
    常见的命名空间有三种层次的用法,接下来我们,定义如下两个命名空间(本节的实验1、2均基于该命名空间):
    1. namespace One {
    2.     int x;
    3.     int y;
    4.     int z;

    5.     void myPrint(){
    6.         cout<<"One::x="<<x<<endl;   //在自己的作用域内打印变量,不会与外界同名变量起冲突
    7.     }
    8. }

    9. namespace Another {
    10.     int x;
    11.     int y;
    12.     int z;

    13.     void myPrint(){
    14.         cout<<"Another::x="<<x<<endl;
    15.     }

    16. }
    复制代码

    以此为基础,展开实验:
    实验1:直接使用命名空间成员,不会产生命名冲突
    1. int main(void){

    2.     One::x = 10;
    3.     Another::x = 15;
    4.     //cout<<x<<endl;   //error:在main中未定义x变量,如果想引用命名空间中的变量x需要加上作用域

    5.     cout<<"One::x="<<One::x<<endl;
    6.     One::myPrint();
    7.     cout<<"Another::x="<<Another::x<<endl;
    8.     Another::myPrint();

    9.     return 0;
    10. }
    复制代码

    实验2:将两个命名空间成员融入同一个环境,可能产生冲突:
    1. int main(void){

    2.     using One::x;    //使用using可对命名空间成员进行解包
    3.     x = 100;
    4.     cout<<x<<endl;
    5.    
    6.     using Another::x;//error:上面已经释放了One命名空间中的变量x,这里再来释放Another中的x,就会产生冲突
    7.     x = 200;
    8.     cout<<x<<endl;

    9.     return 0;
    10. }
    复制代码
    运行结果如下:

    在C/C++中,最小的作用域就是一对"{}"中的内容,我们可以分别对这两个命名空间中的成员操作添加{},使之成为一个新的作用域,就不会报错了。
    实验2改进版:
    1. int main(void){

    2.     int x = 11;    //在main函数中定义一个x,测试对两个命名中的同名x进行操作,最终是否会影响到main中的x
    3.     cout<<"main x="<<x<<endl;
    4.    
    5.     {
    6.         using One::x;    //使用using可对命名空间成员进行解包
    7.         x = 100;
    8.         cout<<"One::x"<<x<<endl;
    9.     }

    10.     {
    11.         using Another::x;//上面已经释放了One命名空间中的变量x,这里再来释放Another中的x,就会产生冲突
    12.         x = 200;
    13.         cout<<"Another::x"<<x<<endl;
    14.     }

    15.     cout<<"main x="<<x<<endl;

    16.     return 0;
    17. }
    复制代码

    由本实验可知:{}中的操作只能影响到括号内部(作用域范围内)的值,在这种情况下,两个命名空间中的同名变量可以"共存",其影响效果也仅限于本作用域
    实验3:命名空间嵌套命名空间
    1. #include<iostream>
    2. using namespace std;

    3. namespace University {

    4.     string name = "Hellow";

    5.     namespace College {

    6.         string name = "Honker";
    7.     }
    8. }

    9. int main(void){

    10.     {
    11.         cout<<"University::name:"<<University::name<<endl;
    12.         cout<<"University::College::name:"<<University::College::name<<endl;
    13.     }

    14.     {
    15.         using namespace University::College;
    16.         cout<<"University::College::name:"<<name<<endl;
    17.     }

    18.     return 0;
    19. }
    复制代码


    由本实验可知:命名空间中可以嵌套命名空间,调用时,如果是嵌套空间,需要添加上被嵌套的命名空间名称
    协作开发
    当项目组中有多人共同开发的时候,每个人可能负责几个模块或是几个文件,但是要求是相同的命名空间,该怎么办呢?
    同名命名空间可以合并,是协同开发的基础,如下:
    1. #include<iostream>
    2. using namespace std;

    3. namespace One {
    4.     int x =1;
    5. }

    6. namespace One {
    7.    
    8.     //int x;    //error同名空间会合并到一个命名空间中去,这里是重定义行为
    9.     int y = 5;
    10. }

    11. int main(void){

    12.     using namespace One;
    13.     cout<<x<<endl;
    14.     cout<<y<<endl;

    15.     return 0;
    16. }
    复制代码

    拓展阅读:
    标准命名空间 std::
    std 是 C++标准库的命名空间,我们输入输出时用到的:cin、cout、endl就定义在其中,如果不进行解包,就无法调用这些类成员。这就是在学习 C++一开始的时候,using namespace std的原故。当然了,前述的几种使用方法依然适用。
    其实,将标准库std全部解包的方法,由于std中包含内容很多,是很容易造成我们在定义变量名的时候造成重名的情况。因此正确的做法是使用到那个类成员就解包哪个类成员,如下两种写法:
    1. #include<iostream>
    2. using std::cout;
    3. using std::cin;
    4. using std::endl;

    5. int main(void){

    6.     int a;
    7.     cin>>a;
    8.     cout<<"Hellow"<<endl;

    9.     return 0;
    10. }
    复制代码
    1. #include<iostream>

    2. int main(void){

    3.     int a;
    4.     std::cin>>a;
    5.     std::cout<<"Hellow"<<std::endl;

    6.     return 0;
    7. }
    复制代码

    但是,由于标准库定义的方法,大家多是耳熟能详,所以一般不会跟标准库产生命名冲突,所以才有了这种偷懒的写法,using namespace std;
    上一篇:10.类型强转
    下一篇:12.字符串类string

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
  • TA的每日心情
    开心
    昨天 12:21
  • 签到天数: 1463 天

    [LV.10]以坛为家III

    发表于 2020-6-16 11:47:49 | 显示全部楼层
    楼主辛苦了,论坛有您更精彩!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2020-8-4 18:30
  • 签到天数: 129 天

    [LV.7]常住居民III

    发表于 2020-6-16 15:13:59 | 显示全部楼层
    楼主辛苦了,论坛有您更精彩!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    4 天前
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    发表于 2020-7-1 10:06:55 来自手机 | 显示全部楼层
    学习了 感谢楼主分享
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    站长推荐 上一条 /3 下一条

    红盟社区--中国红客联盟 

    Processed in 0.098767 second(s), 17 queries.

    站点统计| 举报| Archiver| 手机版| 黑屋 |   

    Powered by HUC © 2001-2017 Comsenz Inc.

    手机扫我进入移动触屏客户端

    关注我们可获取更多热点资讯

    Honor accompaniments. theme macfee

    快速回复 返回顶部 返回列表