Namespace基本知识


published: true
tags:

  • C++
    author: persuez

Namespace

C++中namespace简单来说就是用来控制标志符(如变量,函数,类等)的名字冲突的。

简单术语

  • declarative region: 指标志符声明的区域。具体见图一。
    declarative region.jpg
  • potential scope: 指从该标志符的声明点到其declarative region的终点。也就是一个标志符的最大可能作用域。具体见图二。
  • scope: 指标志符的可见区域。具体见图二。
    potential scope.jpg

namespace关键字

C++中namespace关键字定义了一个declarative region,所以在一个namespace中声明的标志符和其他namespace中声明的同名标志符是没有名字冲突的。

基本语法

我们定义两个namespace,分别命名为Jack和Jill,如下:

// ns.hpp
namespace Jack {
  double pail; // variable declaration
  void fetch(); // function prototype
  int pal; // variable declaration
  struct Well { ... }; // structure declaration
}

namespace Jill {
  double bucket(double n) { ... } // function definition
  double fetch; // variable declaration
  int pal; // variable declaration
  struct Hill { ... }; // structure declaration
}

namespace 可以定义在全局范围内,也可以嵌套在其他namespace中。如果namespace中声明了一些函数或成员函数,那么我们可以通过以下语法定义函数:

// ns.cpp
namespace Jack {
  void fetch()
  {
    ...
  }
}

访问namespace中的成员

除了一般的作用域运算符(::)直接访问namespace中的成员外,我们还有两种方法可以帮助我们轻松地多次访问namespace中的成员:

  • using declaration
  • using directive
    简单来说,前者可以让我们访问特定的成员,而后者则可以让我们访问整个namespace。下面就具体介绍两种方法:
using declaration

这是书本推荐的访问方法。using declaration 将访问的成员加入到它出现的declarative region中。具体用法直接看例子,注释也在样例中:

namespace Jill {
  double bucket(double n) { ... }
  double fetch;
  struct Hill { ... };
}

char fetch; // global variable

int main()
{
  using Jill::fetch; // 一个 using declaration; 它将fetch放到了当前的block declarative region,相当于声明了一个局部变量fetch
  double fetch; // 这将发生错误!因为上条语句已经相当于声明了一个局部变量fetch
  cin >> fetch; // 读入Jill::fetch
  cin >> ::fetch; // 读入全局的fetch
  ...
}

这里需要注意的是using declaration 如果访问的是函数void fetch(),那么语法如下:using Jack::fetch。注意,我们并没有指定函数的返回类型,参数信息,唯一指定的就是函数名,所以using declaration会把该函数的所有重载类型(如果有)都引用进来。

using directive

using directive 将使namespace中的所有成员可访问。如我们平常用的using namespace std;就是一个using directive。我们可以将using directive放在任何地方,但这也会造成它的可以使用的范围不同,但注意使用范围并不代表scope或者potential scope,这个可以从下面的例子看到。和using declaration的另外一个大的不同地方是当它在局部使用时,声明相同的局部变量不会报错,而是声明的局部变量会覆盖掉namespace中的成员。如:

namespace Jill {
  double bucket(double n) { ... }
  double fetch;
  struct Hill { ... };
}

char fetch; // global variable

int main()
{
  using namespace Jill; // Jill::fetch没有局部作用域,因为它没有覆盖掉全局的fetch,并且还可以声明一个局部的fetch,所以作用范围和作用域是不同的。
  Hill Thrill;
  double water = bucket(2); // use Jill::bucket
  double fetch; // 注意:这里不会出现错误,而是覆盖了Jill::fetch
  cin >> fetch; // 读入局部的fetch
  cin >> Jill::fetch; // 读入Jill的fetch
  cin >> ::fetch; // 读入全局fetch
}

int foom()
{
  Hill top; // 出错!
  Jill::Hill top; // 正确
}
用using declaration 还是 using directive

一般来说,using declaration比using directive 安全。因为

  • using declaration明确的告诉我们可以用哪个成员。
  • using diclaration 如果名字冲突了,编译器会报错;而using directive会覆盖了namespace的版本,而不做任何提示。
namespace 嵌套

基本语法如下:

namespace elements {
  namespace fire {
    int flame;
    ...
  }
  float water;
}
// 可以访问fire用
using namespace elements::fire;

namespace myth {
  using Jill::fetch;
  using namespace elements;
  using std::cout;
  using std::cin;
}
int main()
{
  std::cin >> myth::fetch;
  // 或者
  std::cin >> Jill::fetch;

  // 访问 elements
  using namespace myth; // using namespace myth; using namespace elements;这两条语句和上面一条是等价的

}
别名

namespace可以有别名。可以用来简化嵌套namespace的使用:

namespace MEF = myth::elements::fire;
using MEF::flame;

Unnamed namespace

基本语法如下:

namespace {
  int ice;
  int bandycoot;
}

它有以下特点:

  • Unnamed namespace 就像在其前面用了using directive一样,我们可以直接访问其成员。
  • 因为其没有名字,所以只能在当前定义的文件中使用。也就是说,这个提供了一种类似关键字static的能力,只能在内部链接。

公众号

更多好玩的内容请关注我的公众号~会介绍一些 linux 上的效率工具,C 语言, linux 咨询以及 linux 内核源码学习。

  • 19
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
知识图谱算法是指在知识图谱上进行的各种算法,包括实体链接、实体分类、关系抽取、知识推理、知识融合等。下面是一些知识图谱算法的基本知识: 1. 实体链接:将文本中的实体链接到知识图谱中的实体,以便更好地理解文本。实体链接的方法包括基于规则的方法和基于机器学习的方法。 2. 实体分类:将知识图谱中的实体进行分类,以便更好地组织和管理知识。实体分类的方法包括基于规则的方法和基于机器学习的方法。 3. 关系抽取:从文本中抽取实体之间的关系,并将其表示为知识图谱中的关系。关系抽取的方法包括基于规则的方法和基于机器学习的方法。 4. 知识推理:基于知识图谱中的事实和规则,推理出新的知识。知识推理的方法包括基于规则的方法和基于机器学习的方法。 5. 知识融合:将来自不同数据源的知识进行融合,以便更好地组织和管理知识。知识融合的方法包括基于规则的方法和基于机器学习的方法。 下面是一个基于知识图谱的实体链接的例子: ```python import spacy from spacy.matcher import Matcher from rdflib import Graph, Namespace, URIRef # 加载Spacy模型 nlp = spacy.load("en_core_web_sm") # 定义命名空间 DBO = Namespace("http://dbpedia.org/ontology/") # 加载知识图谱 g = Graph() g.parse("dbpedia_2016-10.owl") # 定义实体链接的规则 matcher = Matcher(nlp.vocab) pattern = [{"POS": "PROPN"}, {"POS": "PROPN"}] matcher.add("entity_linking", None, pattern) # 定义实体链接函数 def entity_linking(text): doc = nlp(text) matches = matcher(doc) for match_id, start, end in matches: entity = doc[start:end].text uri = g.qname_to_uri(entity, DBO) if uri: return URIRef(uri) return None # 测试实体链接函数 text = "Barack Obama was born in Hawaii." entity = entity_linking(text) if entity: print(entity) else: print("No entity found.") ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值