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

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

        分类:            c/c++ 36人阅读 评论(0) 收藏 举报

上一篇  using声明、using指示及其作用域详解  说的是函数内部或者全局作用域中使用using声明和using指示的情况,这里说的是在嵌套命名空间中使用using声明与using指示的情况。

//named_namespace.h  命名空间成员声明与定义头文件

  1. #ifndef NAME_17_2_3 
  2. #define NAME_17_2_3 
  3. namespace name_17_2_3 
  4.   class AA   //类AA的定义,例子中用不到,忽略它 
  5.   { 
  6.     AA() {} 
  7.   }; 
  8.   extern int name_17_2_3_fun();  //函数fun声明,定义在命名空间实现文件中 
  9.   extern int i; //同上 
  10.  
  11.   namespace BB 
  12.   { 
  13.     extern int i;  //函数fun声明,定义在命名空间实现文件中 
  14.   } 
  15.  
  16.  
  17. #endif 
#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声明有相同的局部名字,将遇到声明冲突的编译时错误;

  1. //named_namespace.cpp  命名空间成员定义实现文件 
  2.  
  3. #include "named_namespace.h" 
  4. #include <iostream> 
  5. namespace name_17_2_3 
  6.   int i = -1; //命名空间name_17_2_3中名字 i 的定义; 
  7.  
  8.   namespace BB 
  9.   { 
  10.     int i = 10; //嵌套命名空间BB中 i 的定义; 
  11.   } 
  12.  
  13.   int name_17_2_3_fun() 
  14.   { 
  15.     using BB::i;  //对嵌套命名空间BB中的变量 i 进行using声明,变量 i 仅在该成员函数内部可见,因为using声明是局部的,到函数右花括弧以后,变量 i 将不可见; 
  16.     return i;  //不会产生二义性,局部名字屏蔽了外围作用域同名名字,将返回BB中的变量 i,如果去掉上述using声明,将返回命名空间name_17_2_3中的变量 i,如果在该函数内部再定义相同的名字将会遇到声明冲突的编译错误; 
  17.   } 
  18.  
  19.   int m = i; //使用命名空间name_17_2_3中的名字 i; 
//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;
}

2.   嵌套命名空间中的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内部第一行:

  1. //named_namespace.h 命名空间name_17_2_3的实现文件 
  2.  
  3. #include "named_namespace.h" 
  4. #include <iostream> 
  5. namespace name_17_2_3 
  6.   int i = -1; 
  7.  
  8.   namespace BB 
  9.   { 
  10.     int i = 10
  11.   } 
  12.  
  13.   int name_17_2_3_fun() 
  14.   { 
  15.     using namespace BB; //using指示嵌套命名空间BB,根据 ”using指示具有将命名空间成员提升到包含命名空间本身的作用域“ 一句,那么BB的所有成员将被提升到包含BB本身定义的外围命名空间name_17_2_3的作用域中,但是,BB所有成员名字的可见性仅仅局限于:从using指示点开始,直到包含该using指示的作用域的结尾处,在此例中,BB成员名字仅仅在从using namespace BB一句到该函数右花括弧末尾,在此之前并不可见; 
  16.  
  17.  
  18.     int n = i; //本句对名字 i 的使用将产生二义性,因为此处能够看见两个名字,一个是name_17_2_3中的名字 i,一个是using指示的BB中的名字 i; 
  19.     return 0; 
  20.   } 
  21.  
  22.   int m = i; //使用的是命名空间name_17_2_3中的名字 i,BB中名字在此并不可见,因为上述using指示的嵌套命名空间BB的名字可见性在函数name_17_2_3_fun()的末尾处结束; 
  23.  
  24. <span style="color: rgb(0, 0, 0);">为了证明名字 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> 
  25.  
//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()的末尾处结束;

为了证明名字 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;

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

  1. #include "named_namespace.h" 
  2. #include <iostream> 
  3. namespace name_17_2_3 
  4.   int i = -1; 
  5.  
  6.   namespace BB 
  7.   { 
  8.     int i = 10
  9.   } 
  10.  
  11.   int name_17_2_3_fun() 
  12.   { 
  13.     int n = i;  //尽管使用了相同的名字 i, 
  14.     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之前不可见,这与书中讲的是一致的; 
  15.     //int a = i; //此句注释不会发生编译错误,因为虽然using指示BB中的名字 i 与命名空间name_17_2_3中的名字 i 相同,但是并未使用名字 i ,如果去掉注释,那么发生的错误将与第一种情况是一样的,对 i 的使用发生歧义,不知道应该使用嵌套命名空间BB中的 i ,还是外围命名空间name_17_2_3中的 i; 
  16.     return 0; 
  17.   } 
  18.  
  19.     int m = i
#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指示的作用域的结尾处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值