网站首页 美食营养 游戏数码 手工爱好 生活家居 健康养生 运动户外 职场理财 情感交际 母婴教育 生活知识 知识问答

C++ 自定义namespace的使用技巧

时间:2024-10-13 14:58:14

C++给命名冲突引入了namespace(命名空间)概念,从而降低了各种第三方库间的标识符冲突问题。那么如何定义自己的namespace以及如何实现及使用呢?

工具/原料

GNU GCC g++编译器

自定义namespace分离式实现

1、 所谓分离式实现就是指“声明”和“定义”分别保存在不同的文件中,一般讲声明保存在.h文件、定义保存在.cpp文件中。如此放置便可达到分离式方式。 那么将声明和定义分离有什么意义吗?首先从非分离式(声明的同时给出定义)看,其内容一般保存在.h文件中,以供多个源文件引用。但是将定义放在头文件,那么当多个源文件使用#include命令包含此类的头文件便会在链接阶段出现“multiple definition”链接错误!那么想让多个文件使用此头文件,又不引发链接的“multiple definition”错误该怎么办呢? 分离式的实现便可以解决这个问题。因为.h文件中只包含声明,即使被多个源文件引用也不会导致“multiple definition”链接错误。所以分离式实现增强了命名空间的实用性。以下举例说明。(2015-04-11 更新)

2、//Two.h 定义#ifndef TWO_H#define TWO_H#include <string>using namespace std;namespace MyNameSpace{ void Say();}namespace MyPrintSpace{ void Say();}#endif

3、//Two.cpp 实现#include <iostream>#include <string>#include "Two.h"using namespace std;void MyNameSpace::Say(){ cout << "MyNameSpace::Say()" << endl;}void MyPrintSpace::Say(){ cout << "MyPrintSpace::Say()" << endl;}

4、 #include "Two.h"预编译指令只引入了namespace的定义到当前文件中,此时还必须使用‘namespace_name::Identifier’的方式访问名称。1.若想直接使用某个标识符,应该使用如下方法引入标识符:using 命名空间标识符::标识符;2.将namespace下面的所有标识符引入,可使用:using namespace 命名空间标识符;

5、将自定义的namespace的实现和定义分别放在.cpp和.h文件中,达到分离式实现。Two.h文件用于命名空间的声明,Two.cpp文件用于命名空间中函数、类等的实现。

自定义namespace的使用

1、// One.cpp 测试文件#include <iostream>#include <string>#include "Two.h"using namespace std;using namespace MyNameSpace;using namespace MyPrintSpace;void Say(){ cout << "Galobel::NameSpace" << endl;}int main(){ ::Say(); //全局命名空间:: MyNameSpace::Say(); MyPrintSpace::Say(); return 0;}

2、#编写Makefile文件CC=g++OBJS=One.o Two.oNameSpace : ${OBJS} ${CC} -o NameSpace ${OBJS}One.o : One.cpp Two.h ${CC} -c -o One.o One.cppTwo.o : Two.cpp Two.h ${CC} -c -o Two.o Two.cppclean: rm NameSpace One.o Two.o#Terminal中编译$ makeg++ -c -o One.o One.cppg++ -c -o Two.o Two.cppg++ -o NameSpace One.o Two.o

3、运行结果:$ ./NameSpaceGalobel::NameSpaceMyNameSpace::Say()MyPrintSpace::Say()

namespace浅析

1、using声明/using编译指令 using std::cin; // using声明使特定的标识符可用 using namespace std; // using编译指令使整个名称空间可用

2、using编译指令和using声明的比较 使用using编译指令导入一个名称空间中所有的名称与使用多个using声明是不一样的,而更像是大量使用作用域解析运算符。使用using声明时,就好像声明了相应的名称一样。 如果某个名称已经在函数中声明了,则不能用using声明导入相同的名称。然而,使用using编译指令时,将进行名称解析,就像在包含using声明和名称空间本身小声明区域中声明了名称一样。 如果使用using执行导入一个已经声明的名称,则局部名称将隐藏名称空间名,就像隐藏同名的全局变量一样。 不过仍然可以像下面的示例那样使用作用域解析运算符:

3、namespace Jill{ double buket(double n) { ... } double fetch; struct Hill { ... };}char fetch; // gloabl namespace,全局空间int main( ){ using namespace Jill; // 导入命名空间所有名称 Hill Thrill; double water = bucktet(2); // use Jill:bucket( ) double fetch; // 隐藏Jill::fetch cin >> fetch; // local fetch cin >> ::fetch; // 全局fetch cin >> Jill::fetch; // Jill::fetch}int foom( ){ Hill top; //错误 Jill::Hill crest; //valid}// 假设名称空间和声明区域定义了相同的名称。如果试图使用using声明将名称空间的名称导入该声明区域,则这两个名称会发生冲突,从而出错。如果是会用using编译指令将该名称空间的名称导入该声明区域,则局部版本将隐藏名称空间版本。//////////////////////////////////////////////////////////注:以上内容摘录自《C++ Primer Plus(第6版)中文版》第9章 内存模型和名称空间 第328页

4、 一般说来,使用using声明比较使用using编译指令更安全,这是由于它(using declaration)只导入指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译指令导入所有名称,包括可能不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖空间版本,而编译器并不会发出警告。另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。// in file One.hnamespace seek{ void Func();}//////////// end One.h /////////// in file Two.hnamespace seek{ void Add(double a, double b);}//////////// end Two.h ///////////在文件One.h和Two.h中都有命名空间seek的声明,这种写法是正确的。

更新记录

1、04-02 第一次更新2015-04-11 第二次更新

© 2026 五度知识库
信息来自网络 所有数据仅供参考
有疑问请联系站长 site.kefu@gmail.com