现在的位置: 首页 > 综合 > 正文

一 : using声明、using指示及其作用域详解 一 : using声明、using指示及其作用域详解

2013年02月22日 ⁄ 综合 ⁄ 共 8327字 ⁄ 字号 评论关闭

一 : using声明、using指示及其作用域详解

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

1. using 声明:一个using声明一次只能引入一个命名空间成员,从using声明点开始,直到包含该using声明的作用域结尾,声明的名字仅仅在该作用域是可见的,外部作用域中相同的名字被屏蔽,它可以出现在全局作用域,局部作用域或者命名空间作用域中,类中的using声明局限于使用其基类中定义的名字;

using声明将名字直接放入出现using声明的作用域,好像using声明是命名空间成员的局部别名一样,这种声明是局部化的,名字仅仅在using声明被包含的作用域有效;

一定记住using声明是局部的,它涉及到的作用域只有一个,就是从using声明点开始,直到包含该using声明的作用域结尾,别无他处;

有如下命名空间:

  1. //头文件 named_namespace.h
  2. #ifndef NAME_17_2_3
  3. #define NAME_17_2_3
  4. namespace name_17_2_3
  5. {
  6. class AA
  7. {
  8. AA() {}
  9. };
  10. extern int name_17_2_3_fun(); //声明
  11. extern int i; //声明
  12. }
  13. #endif
  14. //实现文件 named_namespace.cpp
  15. #include "named_namespace.h"
  16. namespace name_17_2_3
  17. {
  18. int name_17_2_3_fun() //定义
  19. {
  20. return 998;
  21. }
  22. int i; //定义
  23. }

使用命名空间的文件:

  1. #include <iostream>
  2. #include "named_namespace.h"
  3. using namespace std;
  4. using name_17_2_3::i; //using声明,在全局作用域声明命名空间name_17_2_3的成员变量i,全局可见;
  5. using name_17_2_3::name_17_2_3_fun; //using声明,声明了命名空间name_17_2_3的成员函数name_17_2_3_fun;
  6. int i = 200; //全局变量i,将与using声明引入的命名空间的成员变量i冲突
  7. int main()
  8. {
  9. cout << "i="
    << i
    << endl; //调用哪一个 i 呢?
  10. cout << "name_17_2_3_fun():"
    << name_17_2_3_fun()
    << endl; //调用命名空间name_17_2_3的成员函数
  11. return 0;
  12. }

在上述代码中的全局作用域中,有两个变量 i 可见,一个是全局变量 i ,另一个是using声明引入的命名空间name_17_2_3的成员变量i,因为using声明处于全局作用域,这时编译就会出错,因为两个声明冲突了,而成员函数则不冲突因为只有一个声明;

如果将using name_17_2_3::i; 放入main函数,那这个using声明就是局部的,命名空间name_17_2_3的成员变量i就是局部变量,将会屏蔽全局变量i,编译通过,如果想使用全局变量i时,可以使用作用域操作符::对i进行限定,例如:::i表示全局变量i;

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

其实不太好理解的是最后一句话:“包含命名空间本身的作用域” 和 “usin指示的最近作用域” 分别指的是哪个作用域,经过昨天一下午的试验,今早上公交车上一路的琢磨,终于搞明白了,下边进行详细解释:

例如:将上述代码的修改如下:

  1. #include <iostream>
  2. #include "named_namespace.h" //将命名空间name_17_2_3插入到当前位置,也就是全局作用域,相当于在此处定义命名空间;
  3. using namespace std;
  4. using namespace name_17_2_3; //using指示,处于全局作用域,;
  5. int i = 200; //全局变量;
  6. int main()
  7. {
  8. //using namespace name_17_2_3;
  9. cout << "i="
    << i
    << endl; //调用哪一个 i 呢?编译器不知道应该使用哪个变量 i;
  10. return 0;
  11. }

a:因为#include指令将头文件包含的命名空间name_17_2_3插入到了main之前,这与在main之前定义一个命名空间是一样的,main之前属于全局作用域,所以命名空间name_17_2_3就被包含在了全局作用域中,那这句话 “包含命名空间本身的作用域“ 中的 “作用域” 指的就是全局作用域了,那么命名空间name_17_2_3的所有成员自然而然就在全局作用域中可见了,虽然在全局作用域可见,但是,如果把using指示写在main函数内部,那么只有main函数内可以访问所有成员名字,书上也有明确说明,详细解释可以接着往下看;

所以:上述代码中,在全局作用域通过using指示的命名空间name_17_2_3,好像name_17_2_3的所有成员在mai之前定义一样,所以在使用变量 i 时将遇到编译错误,不知道应该使用哪个位置的变量 i;

现在修改以上代码,把using指示写在main函数内部,为了容易做实验,就写在了main内部第一个引用变量 i 的语句后边:

  1. #include <iostream>
  2. #include "named_namespace.h"
  3. using namespace std;
  4. int i = 200; //全局变量;
  5. int main()
  6. {
  7. cout << "i="
    << i
    << endl; //在此语句之前,只有一个全局变量 i 可见,调用的是全局变量i,即 int
    i = 200,如果此处要使用name_17_2_3的成员,必须以name_17_2_3进行限定;
  8. using namespace name_17_2_3;
  9. cout << "i="
    << i
    << endl; //调用哪一个 i 呢?经过using指示后,从此处指示点开始,name_17_2_3的所有成员可见,就会有一个main之前定义的全局变量 i, 和一个被using指示引入的变量 i,所以使用 i 会产生歧义;
  10. return 0;
  11. }

b:从上述例子可以看出,只有在using指示点以后,name_17_2_3的所有成员名字才可见,才可以不带命名空间名字使用成员名字,那么 ”usin指示的最近作用域“ 中的作用域指的就是:”从using指示点开始,直到包含using指示的作用域的末尾“ 这样的一个作用域;

总结:以上两种情况,不管将using指示写在main内部还是外部,都将把name_17_2_3的所有成员引入全局作用域,因为name_17_2_3被#include指令插入到了全局作用域,相当于在全局作用域定义它,虽然如此,只有在using指示点以后才能够以短格式即不带限定符使用这些成员;

1. using 声明:一个using声明一次只能引入一个命名空间成员,从using声明点开始,直到包含该using声明的作用域结尾,声明的名字仅仅在该作用域是可见的,外部作用域中相同的名字被屏蔽,它可以出现在全局作用域,局部作用域或者命名空间作用域中,类中的using声明局限于使用其基类中定义的名字;

using声明将名字直接放入出现using声明的作用域,好像using声明是命名空间成员的局部别名一样,这种声明是局部化的,名字仅仅在using声明被包含的作用域有效;

一定记住using声明是局部的,它涉及到的作用域只有一个,就是从using声明点开始,直到包含该using声明的作用域结尾,别无他处;

有如下命名空间:

  1. //头文件 named_namespace.h
  2. #ifndef NAME_17_2_3
  3. #define NAME_17_2_3
  4. namespace name_17_2_3
  5. {
  6. class AA
  7. {
  8. AA() {}
  9. };
  10. extern int name_17_2_3_fun(); //声明
  11. extern int i; //声明
  12. }
  13. #endif
  14. //实现文件 named_namespace.cpp
  15. #include "named_namespace.h"
  16. namespace name_17_2_3
  17. {
  18. int name_17_2_3_fun() //定义
  19. {
  20. return 998;
  21. }
  22. int i; //定义
  23. }

使用命名空间的文件:

  1. #include <iostream>
  2. #include "named_namespace.h"
  3. using namespace std;
  4. using name_17_2_3::i; //using声明,在全局作用域声明命名空间name_17_2_3的成员变量i,全局可见;
  5. using name_17_2_3::name_17_2_3_fun; //using声明,声明了命名空间name_17_2_3的成员函数name_17_2_3_fun;
  6. int i = 200; //全局变量i,将与using声明引入的命名空间的成员变量i冲突
  7. int main()
  8. {
  9. cout << "i="
    << i
    << endl; //调用哪一个 i 呢?
  10. cout << "name_17_2_3_fun():"
    << name_17_2_3_fun()
    << endl; //调用命名空间name_17_2_3的成员函数
  11. return 0;
  12. }

在上述代码中的全局作用域中,有两个变量 i 可见,一个是全局变量 i ,另一个是using声明引入的命名空间name_17_2_3的成员变量i,因为using声明处于全局作用域,这时编译就会出错,因为两个声明冲突了,而成员函数则不冲突因为只有一个声明;

如果将using name_17_2_3::i; 放入main函数,那这个using声明就是局部的,命名空间name_17_2_3的成员变量i就是局部变量,将会屏蔽全局变量i,编译通过,如果想使用全局变量i时,可以使用作用域操作符::对i进行限定,例如:::i表示全局变量i;

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

其实不太好理解的是最后一句话:“包含命名空间本身的作用域” 和 “usin指示的最近作用域” 分别指的是哪个作用域,经过昨天一下午的试验,今早上公交车上一路的琢磨,终于搞明白了,下边进行详细解释:

例如:将上述代码的修改如下:

  1. #include <iostream>
  2. #include "named_namespace.h" //将命名空间name_17_2_3插入到当前位置,也就是全局作用域,相当于在此处定义命名空间;
  3. using namespace std;
  4. using namespace name_17_2_3; //using指示,处于全局作用域,;
  5. int i = 200; //全局变量;
  6. int main()
  7. {
  8. //using namespace name_17_2_3;
  9. cout << "i="
    << i
    << endl; //调用哪一个 i 呢?编译器不知道应该使用哪个变量 i;
  10. return 0;
  11. }

a:因为#include指令将头文件包含的命名空间name_17_2_3插入到了main之前,这与在main之前定义一个命名空间是一样的,main之前属于全局作用域,所以命名空间name_17_2_3就被包含在了全局作用域中,那这句话 “包含命名空间本身的作用域“ 中的 “作用域” 指的就是全局作用域了,那么命名空间name_17_2_3的所有成员自然而然就在全局作用域中可见了,虽然在全局作用域可见,但是,如果把using指示写在main函数内部,那么只有main函数内可以访问所有成员名字,书上也有明确说明,详细解释可以接着往下看;

所以:上述代码中,在全局作用域通过using指示的命名空间name_17_2_3,好像name_17_2_3的所有成员在mai之前定义一样,所以在使用变量 i 时将遇到编译错误,不知道应该使用哪个位置的变量 i;

现在修改以上代码,把using指示写在main函数内部,为了容易做实验,就写在了main内部第一个引用变量 i 的语句后边:

  1. #include <iostream>
  2. #include "named_namespace.h"
  3. using namespace std;
  4. int i = 200; //全局变量;
  5. int main()
  6. {
  7. cout << "i="
    << i
    << endl; //在此语句之前,只有一个全局变量 i 可见,调用的是全局变量i,即 int
    i = 200,如果此处要使用name_17_2_3的成员,必须以name_17_2_3进行限定;
  8. using namespace name_17_2_3;
  9. cout << "i="
    << i
    << endl; //调用哪一个 i 呢?经过using指示后,从此处指示点开始,name_17_2_3的所有成员可见,就会有一个main之前定义的全局变量 i, 和一个被using指示引入的变量 i,所以使用 i 会产生歧义;
  10. return 0;
  11. }

b:从上述例子可以看出,只有在using指示点以后,name_17_2_3的所有成员名字才可见,才可以不带命名空间名字使用成员名字,那么 ”usin指示的最近作用域“ 中的作用域指的就是:”从using指示点开始,直到包含using指示的作用域的末尾“ 这样的一个作用域;

总结:以上两种情况,不管将using指示写在main内部还是外部,都将把name_17_2_3的所有成员引入全局作用域,因为name_17_2_3被#include指令插入到了全局作用域,相当于在全局作用域定义它,虽然如此,只有在using指示点以后才能够以短格式即不带限定符使用这些成员;

抱歉!评论已关闭.