C++你所不知道的命名空间

小灰灰 2023-06-30 15:55 87阅读 0赞

我们每天都在用using namespace std;但你对命名空间了解多少?

这是个啥?

命名空间是一种机制,用来把单个标识符下存在大量有逻辑联系的程序实体组合到一起,并以此标识符作为此组群的名字。
换一种说法,就是一个集合,其关键字就是命名空间的名字

  1. using namespace name
  2. {
  3. /* code */
  4. } ;// namespace name

相关的几个概念(这三个作用域逐次减小)

  • 声明域(declaration region):声明标识符的区域
  • 潜在作用域(potential scope):从声明点开始,到声明域末尾的区域。(因为C++是先声明后使用的原则,所以声明点之前的声明域中,标识符是不能用的)
  • 作用域(scope):即标识符对程序可见的范围,即真正在使用的范围
    CAUTION:MS的MFC(微软基础类库)中没有使用命名空间,但.NET有很多使用

定义命名空间

命名空间可以定义有名的和无名的(就像你定义一个struct结构体一样)
结合一个小例子:

  1. namespace Outer
  2. {
  3. int i; // 命名空间Outer的成员i的内部定义
  4. namespace Inner // 子命名空间Inner的内部定义
  5. {
  6. void Fun1() { i++; } // i为 Outer::i
  7. int i;
  8. void Fun2() { i++; } // Inner::i
  9. void Fun3();
  10. } // namespace Inner
  11. void Fun1();
  12. // namespace Inner2; // 错误,不能 声明 (而非定义)子命名空间
  13. } // namespace Outer
  14. void Outer::Fun1()
  15. {
  16. i--;
  17. }
  18. void Outer::Inner::Fun3()
  19. {
  20. i--;
  21. }
  • 不能在命名空间的定义中声明(另一个嵌套的)子命名空间,只能定义子命名空间
  • 命名空间必须定义在头文件中,所以记得新建一个 .h 文件哦
  • 命名空间是开放的,这也就意味着可以随时将新的成员名称加入到已有的命名空间中去,但规则嘛,就是不能直接使用命名空间名::成员名的形式,而必须先在命名空间的定义中声明,方法是多次声明和定义同一命名空间,每次添加新成员
  • 还可以组合现有的命名空间(使用using)
    For example:

    namespace sample
    {

    1. int i;
    2. void Fun1();

    } // 现在有成员i, Fun1()
    namespace sample // 重新定义命名空间sample
    {

    1. int j;
    2. void Fun2()

    } // 现在有成员i, Fun1(), j, Fun2()
    namespace sample1
    {

    1. using namespace sample;
    2. void Fun3();

    } // 组合命名空间


使用它!

  • 使用作用域运算符“: :“ (就像你对类成员所做的那样)
  • 使用using指令

    • 标准C++库(不包括标准C库)中所包含的所有内容(包括常量,变量,结构,类和函数, etc.)都被定义在命名空间std(standard标准)中了,但预编译(#include) 部分应包含不带.h的标准头文件(例如#include <iostream>)然后再using namespace std;
    • using自定义的命名空间:
      using namespace 命名空间名[ ::子命名空间名1…… ]
      当只有一个字空间时,可以略去不写 [ ]
      using namespace Outer::Inner;
    • 要写子命名空间而不是只写(也不用/不能额外写)基命名空间,不然很有可能引起名称冲突
    • 剩下的就像使用类一样
  • 使用using声明

    • using 命名空间名::[子命名空间名::子子……]成员名;
    • 用处相当于对于单独一个成员免去每一次都写作用域运算符的麻烦,但该命名空间下的其他成员依然要依靠作用域运算符来定位
  • using指令和using声明的比较

    • using指令使用后,可以一劳永逸,它对整个命名空间所有成员都有效;但using声明却必须对不同成员分别声明
    • 但一般来说,using声明会更加安全。因为using声明只会导入指定的名称,如果改名称与局部名称冲突,编译器会报错。而using指令导入的,包括那些根本用不到的名称,且如果其中有 名称与局部名称冲突,编译器不会发出任何警告信息,而是仅仅用局部名称覆盖命名空间中的同名成员
    • Conclusion:虽然使用命名空间的方法有多种可供选择,但不能贪图方便而一味使用using指令,那样就背离了设计命名空间的初衷,也失去了命名空间本应有的防止名称冲突的功能

发表评论

表情:
评论列表 (有 0 条评论,87人围观)

还没有评论,来说两句吧...

相关阅读