当前位置: 首页 > news >正文

using声明、using指示用于嵌套命名空间时的作用域

这里说的是在嵌套命名空间中使用using声明与using指示的情况。
//named_namespace.h 命名空间成员声明与定义头文件

    #ifndef NAME_17_2_3  
    #define NAME_17_2_3  
    namespace name_17_2_3  
    {  
      class AA   //类AA的定义,例子中用不到,忽略它  
      {  
        AA() {}  
      };  
      extern int name_17_2_3_fun();  //函数fun声明,定义在命名空间实现文件中  
      extern int i; //同上  

      namespace BB  
      {  
        extern int i;  //函数fun声明,定义在命名空间实现文件中  
      }  

    }  

    #endif  
1.  嵌套命名空间中的using声明:

嵌套命名空间中的using声明也比较简单,被using声明的名字是局部的,从using声明点开始,到包含该声明的作用域的结尾处可见,外围中的同名名字将被该局部名字屏蔽,在声明时进行检查,如果在using声明作用域内,与using声明有相同的局部名字,将遇到声明冲突的编译时错误;
    //named_namespace.cpp  命名空间成员定义实现文件  

    #include "named_namespace.h"  
    #include <iostream>  
    namespace name_17_2_3  
    {  
      int i = -1; //命名空间name_17_2_3中名字 i 的定义;  

      namespace BB  
      {  
        int i = 10; //嵌套命名空间BB中 i 的定义;  
      }  

      int name_17_2_3_fun()  
      {  
        using BB::i;  //对嵌套命名空间BB中的变量 i 进行using声明,变量 i 仅在该成员函数内部可见,因为using声明是局部的,到函数右花括弧以后,变量 i 将不可见;  
        return i;  //不会产生二义性,局部名字屏蔽了外围作用域同名名字,将返回BB中的变量 i,如果去掉上述using声明,将返回命名空间name_17_2_3中的变量 i,如果在该函数内部再定义相同的名字将会遇到声明冲突的编译错误;  
      }  

      int m = i; //使用命名空间name_17_2_3中的名字 i;  
    }  
  1. 嵌套命名空间中的using指示:

嵌套命名空间中的using指示的使用与在函数内部或外部使用一样:using指示使得特定命名空间的所有名字可见,从using指示点开始(这点同using声明一致),对名字可以不加限定符使用,直到包含using指示的作用域的末尾;using指示具有将命名空间成员提升到包含命名空间本身和usin指示的最近作用域的效果;

一定记住,当using指示的命名空间中的名字与使用代码中的名字同名即发生二义性时,如果没有对名字进行使用,比如赋值与被赋值等,此时编译不会发生错误,如果使用了该名字,那么就会发生二义性的编译时错误,using指示是在使用时进行名字检查,而using声明是在声明时就立即检查名字,这点是不同的;

下面将结合嵌套命名空间再把上述说明解释一遍,看命名空间name_17_2_3的实现文件:named_namespace.cpp,修改代码如下:

为了说明被using指示的名字可见性的位置,就是从哪个位置开始可见,到哪个位置结束,分了两种情况讨论:

第一种情况:using指示位置放在了使用被指示名字语句(int n = i;)的前边,函数name_17_2_3_fun内部第一行:

    //named_namespace.h 命名空间name_17_2_3的实现文件  

    #include "named_namespace.h"  
    #include <iostream>  
    namespace name_17_2_3  
    {  
      int i = -1;  

      namespace BB  
      {  
        int i = 10;  
      }  

      int name_17_2_3_fun()  
      {  
        using namespace BB; //using指示嵌套命名空间BB,根据 ”using指示具有将命名空间成员提升到包含命名空间本身的作用域“ 一句,那么BB的所有成员将被提升到包含BB本身定义的外围命名空间name_17_2_3的作用域中,但是,BB所有成员名字的可见性仅仅局限于:从using指示点开始,直到包含该using指示的作用域的结尾处,在此例中,BB成员名字仅仅在从using namespace BB一句到该函数右花括弧末尾,在此之前并不可见;  


        int n = i; //本句对名字 i 的使用将产生二义性,因为此处能够看见两个名字,一个是name_17_2_3中的名字 i,一个是using指示的BB中的名字 i;  
        return 0;  
      }  

      int m = i; //使用的是命名空间name_17_2_3中的名字 i,BB中名字在此并不可见,因为上述using指示的嵌套命名空间BB的名字可见性在函数name_17_2_3_fun()的末尾处结束;  

    <span style="color:#000000;">为了证明名字 i 的可见位置到函数name-17_2_3_fun的右花括弧处结束,做一个验证:将头文件中i的声明注释掉,命名空间name_17_2_3中的i的定义注释掉,再编译时提示”i在此作用域(命名空间name_17_2_3中)尚未声明“,充分证明虽然嵌套命名空间BB中的所有名字提示到了包含BB的命名空间name_17_2_3中,但是BB名字的可行性仅仅局限于使用using指示的函数name_17_2_3_fun中,即函数name_17_2_3_fun的右花括弧之后再也看不见嵌套命名空间BB中所有名字,包括 i;</span>  

    }  

第二种情况:using指示位置放在了使用被指示名字的语句(int n = i;)的后一行,函数name_17_2_3_fun内部:

    #include "named_namespace.h"  
    #include <iostream>  
    namespace name_17_2_3  
    {  
      int i = -1;  

      namespace BB  
      {  
        int i = 10;  
      }  

      int name_17_2_3_fun()  
      {  
        int n = i;  //尽管使用了相同的名字 i,  
        using namespace BB;  //放在了int n = i后边,BB的所有成员仍然被提升到包含BB本身定义的外围命名空间name_17_2_3的作用域中,这点和第一种情况是一致的,但是BB所有成员名字的可见性发生了一点变化:在此例中,BB成员名字从using namespace BB一句到该函数右花括弧末尾,在此之前并不可见,也就是说,第一句的位置看不见BB中的名字,对n的赋值,使用的是命名空间name_17_2_3中的 i,因为BB::i 在using之前不可见,这与书中讲的是一致的;  
        //int a = i; //此句注释不会发生编译错误,因为虽然using指示BB中的名字 i 与命名空间name_17_2_3中的名字 i 相同,但是并未使用名字 i ,如果去掉注释,那么发生的错误将与第一种情况是一样的,对 i 的使用发生歧义,不知道应该使用嵌套命名空间BB中的 i ,还是外围命名空间name_17_2_3中的 i;  
        return 0;  
      }  

        int m = i;  
    }  

经过上述两种情况充分证明,using指示的名字作用域,从using指示点开始,直到包含该using指示的作用域的结尾处。

相关文章:

  • C语言运算符优先级列表
  • 康托展开和逆康托展开
  • C语言中scanf函数的实现
  • 【codevs 1225】八数码难题
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • 浅谈一类积性函数的前缀和
  • Codeforces Round #363 (Div. 2)[B]One Bomb
  • BFS、双向BFS和A*
  • 二分的模板(花式二分)
  • STL之set集合容器
  • NOIP2016#模拟考试 Day.1# T1 洗澡
  • NOIP2016#模拟考试 Day.1# T3 导航软件
  • [hdu 4405] Aeroplane chess [概率DP 期望]
  • NOIP2016#模拟考试 Day.2# T2 网络修复 【LCA + 并查集】
  • NOIP2016#模拟考试 Day.2# T3 王位继承
  • $translatePartialLoader加载失败及解决方式
  • 《Java编程思想》读书笔记-对象导论
  • 【347天】每日项目总结系列085(2018.01.18)
  • fetch 从初识到应用
  • httpie使用详解
  • Java小白进阶笔记(3)-初级面向对象
  • jQuery(一)
  • JS基础之数据类型、对象、原型、原型链、继承
  • node入门
  • Quartz初级教程
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Vue ES6 Jade Scss Webpack Gulp
  • zookeeper系列(七)实战分布式命名服务
  • 彻底搞懂浏览器Event-loop
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 搭建gitbook 和 访问权限认证
  • 反思总结然后整装待发
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • ​Java并发新构件之Exchanger
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ![CDATA[ ]] 是什么东东
  • #《AI中文版》V3 第 1 章 概述
  • $NOIp2018$劝退记
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (C++17) std算法之执行策略 execution
  • (C语言)共用体union的用法举例
  • (八)c52学习之旅-中断实验
  • (超详细)语音信号处理之特征提取
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)Oracle存储过程编写经验和优化措施
  • (转)项目管理杂谈-我所期望的新人
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)