美文网首页
名称空间

名称空间

作者: 一半晴天 | 来源:发表于2018-03-18 17:58 被阅读8次

引言

C 的全局性名称空间容易生成名称冲突的问题。
想法1:名称属于编译单元,需要使用 extern 来公开。 失败!
想法2:由类型安全的连接机制: extern "C" { /*..*/ } 想到 extern XXX { /*...*、 },要从其他作用域需要使用 XXX:: 的访问形式。由于时间关系没有跟进。
提案1: 建议采用记法: bundle XXX { /*...*/}
提案2: 采用 :: XXX :: { /*...*/ }

问题

在 C 中常见的一些解决名称冲突的办法是在名称前面加前缀。
有人使用宏机制来加前缀 。

#define my(X) myprefix_##X
char my(f)(char);

另一种方式是使用一个类包裹。

解决方案的思想

  1. 能够在连接两个库时不出现名称冲突。
  2. 能够在引进新的名称时不必担心与别人已经有的名称冲突。
  3. 能够在库的实现里增加一个名称而又不影响库的用户。
  4. 能够从两个不同的库中选择名称,即使这两个库恰好使用了同样的名称。
  5. 能够不修改有关的函数本身,而消解掉出现的名称冲突。
  6. 增加新名称,不会影响其他名称空间的代码。
  7. 能够避免名称空间的名称之间发生冲突。
  8. 有处理标准库的能力。
  9. 与 C 和 C++兼容。
  10. 不增加任何连接或运行时的额外成本。
  11. 不增加比使用全局名称的用户更多描述上的麻烦。
  12. 使人能够在使用名称的代码中显式指明某个名称的假定出处。

一个解决方案: 名称空间

  1. 一种定义作用域机制,即名称空间,用于放置传统 C 和 C++ 全局声明。这种作用域可以命名,访问名称空间成员采用访问类成员的传统记法:namespace_name::member_name。 事实上,类作用域可以看成是名称空间使用域的一种特殊情况。
  2. 一种为名称空间定义局部同义词的机制。
  3. 一种允许不显示写出 namespace_name:: 限定词而访问名称空间成员的机制:使用声明。
  4. 一种允许不显示写出 namespace_name:: 限定词而直接访问名称空间的全部成员的机制: 使用指示。

以下面的名称空间声明为例:

namespace A{
  void f(int);
  void f(char);
  class String { /*...*/ };
  // ...
}
  1. 通过显式限定直接使用:
A::String s1 = "Anne";
void g1(){
  A::f(1);
}
  1. 导入个别名称:
using A::String;
String s2 = "Nicholas";

void g2(){
   using A::f; 
   f(2);
}
  1. 全部导入:
using namespace A;
String s3 = "Marian";
void g3(){
  f(3);
}

上面的三种方式是在多种观点中长时间讨论的结果。

使用名称空间投入使用

  1. 对于原来的 C 标准库,可以通过使用名称空间+使用指示是一种好的解决方案。如:
// stdio.h
namespace std{
  int printf(const char * ...);
}
using namespace std;

使用指示可以认为是一种转变工具,来自本名称空间不需要限定,这方面的行为跟类完全一样。

名称空间的别名。

namespace ATT = American_Telephone_and_Telegraph;
这个特征还允许用户引用 “某个库” 而不必准确说出每次实际上使用的是哪个库。也可以用来组合多个名称空间。

利用名称空间管理版本问题

// lib.h 旧版本
namespace lib = release1;
// 新版本
namespace lib =release2;

其他细节

  1. 使用声明向局部作用域添加一些内容,使用指示则不添加任何内容,只是使一些名称能够被访问,例如:
namespace X {
  int i,j,k;
}
int k;

void f1(){
  int i = 0;
  using namespace X;
  i++;
  j++;
  k++;// error: X::k or  global k ?
  ::k++;
  X::k++;
}

void f2(){
  int i = 0;
  using X::i; // error: Target of using declaration conflicts with declaration already in scope
  using X::j;
  using X::k;
  i++;
  j++;
  k++;
}

特别地,与使用指示有关的错误都只在使用点检查。这样不会因为潜在的失败造成程序失败。示例如下:

namespace A {
  int x;
}

namespace B  {
  int x;
}

void f(){
  using namespace A;
  using namespace B;
  A::x++; // ok
  B::x++; // ok
  x++; // Reference to 'x' is ambiguous
}

  1. 全局作用域
    引进名称空间后,全局作用域变成了特殊的名称空间。值得说明的是全局就意味着全局,而不是外层的最近名称空间。

  2. 重载
    允许跨名称空间的重载。如:

namespace A {
  void f(int);
}
using namespace A;

namespace B  {
  void f(char);
}
using namespace B;

void f(){
  f('a'); // calls B::f(char)
}
  1. 名称空间允许嵌套。

  2. 名称空间是开放的,也就是说允许在多个名称空间声明中将各种名称加进一个名称空间中。例如标准库名称空间 std 就是由多个模块组成的。

对类的影响

可以把类看成是一种名称空间。

  1. 一个类的成员将遮蔽其基类中有同样名称的成员。名称空间对此做出的解释就是,派生类相当于是创建了一个嵌套的名称空间。通过声明可以将基类的函数引入到作用域,例如:
class B{
public:
  void f(char);
};
class D: public B{
public:
  void f(int);
  using B::f; // bring B::f into D to enable overloading
};

void f(D& d){
  d.f('c'); // calls D::f(char)!
}

using B::f; 这一方法也可以消除多继承中同名函数的歧义性。同样可用于调整方法的访问方面声明。以替换老式的访问声明方式。

  1. 清除全局的 static
    原来函数可以声明在一个匿名的名称空间以与头文件中的名称发生冲突。
    即:
    namespace { /**/ } 相当于
namespace unique_name{ /* ... */ }
using namespace unique_name;

与 C 语言的兼容性

  1. 具有 C 连接的函数也可以放进一个名称空间中:
namespace X{
  extern "C" void f(int);
 void g(int);
}

不过这要求C 函数的名称的唯一性,即使他们在不同的名称空间中声明,因为他们终穷还是需要按 C 的链接规则来使用,否则将依赖于一些特定的连接名称生成规则来引用 。

相关文章

  • 名称空间

    引言 C 的全局性名称空间容易生成名称冲突的问题。想法1:名称属于编译单元,需要使用 extern 来公开。 失败...

  • 名称空间

    命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的...

  • Hbase

    创建名称空间 create_name ‘名称’ 展示名称空间 list_namespace 列出名称空间的所有表 ...

  • 1.Python语言基础

    Python的名称空间与作用域 名称空间名称空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通...

  • 15.Python之名称空间与作用域

    Python之名称空间与作用域 名称空间名称空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通...

  • Python名称空间

    用一个全家桶一样的例子开启讨论! 下面来逐个分析一下。 在逐个分析之前,对python的名称解析做一下说明。pyt...

  • xml名称空间

    原文链接http://zhhll.icu/2020/xml/xml%E5%90%8D%E7%A7%B0%E7%A9...

  • 11. Python之名称空间与作用域

    1 名称空间 1.1 内置名称空间 1.1.1 存放的名字 1.1.2 存活周期 1.2 全局名称空间 1.2.1...

  • Python之路11:函数之命名空间,闭包,生成器,迭代器

    命名空间 名称空间是存放变量名和赋值绑定关系的地方 名称空间共 3 种: locals: 是函数内的名称空间,包括...

  • C#随笔1

    1命名空间 语法 namespace 命名空间名称{若干个类型} ORnamespace 命名空间名称.子命名...

网友评论

      本文标题:名称空间

      本文链接:https://www.haomeiwen.com/subject/fyqeqftx.html