-
2021-07-30 18:20:52
匿名命名空间的作用是该命名空间只能在本文件使用,相当于C语言的static.
更多相关内容 -
C++匿名命名空间
2021-03-15 09:53:31编译器在内部会为这个命名空间生成一个唯一的名字,而且还会为这个匿名的命名空间生成一条using指令。所以上面的代码在效果上等同于: namespace __UNIQUE_NAME_ { char c; int i; double d; } using namespace ...当定义一个命名空间时,可以忽略这个命名空间的名称:
namespce { char c; int i; double d; }
编译器在内部会为这个命名空间生成一个唯一的名字,而且还会为这个匿名的命名空间生成一条using指令。所以上面的代码在效果上等同于:
namespace __UNIQUE_NAME_ { char c; int i; double d; } using namespace __UNIQUE_NAME_;
在匿名命名空间中声明的名称也将被编译器转换,与编译器为这个匿名命名空间生成的唯一内部名称(即这里的__UNIQUE_NAME_)绑定在一起。还有一点很重要,就是这些名称具有internal链接属性,这和声明为static的全局名称的链接属性是相同的,即名称的作用域被限制在当前文件中,无法通过在另外的文件中使用extern声明来进行链接。如果不提倡使用全局static声明一个名称拥有internal链接属性,则匿名命名空间可以作为一种更好的达到相同效果的方法。
注意:命名空间都是具有external 连接属性的,只是匿名的命名空间产生的__UNIQUE_NAME__在别的文件中无法得到,这个唯一的名字是不可见的.
C++ 新的标准中提倡使用匿名命名空间,而不推荐使用static,因为static用在不同的地方,涵义不同,容易造成混淆.另外,static不能修饰class。
另一篇;
今天得到来自google的老大的指点,学习了一个新的用法:匿名命名空间。 C++另外有一种匿名的命名空间,来保证生成的符号是局部的,这样对于匿名空间中的变量等,外部都是不可见的.
//test3.cpp static void bar(){} namespace //匿名的命名空间 { float bar2; int foo; } //test4.cpp extern int foo; extern void bar(); extern float bar2; int main() { bar(); //外部的bar()被声明为static,这里链接不到符号.不能访问 bar2 = 0.1f; //外部的匿名空间哩,这里也不能访问. foo = 0xFF; return 0; };//如果将test4的目标和test3的目标进行链接,实际上是找不到这些符号的.链接会失败.
匿名的命名空间是C++的特性,相对于C的static声明来说,可以在匿名的空间里面声明很多变量和函数,这样可以省去了对每个变量和函数添加static声明. 实质上匿名空间的功能跟static声明是一样的.
对于一个大型的C语言软件项目,给函数和全局变量起名不是一个容易的事情,因为必须考虑有没有可能与其它程序员写的代码冲突,多数的做法是对每个模块的一组函数名加个特定前缀,如HTRequest_setInternal、HTRequest_internal等。这使得程序员每次调用这些函数时都必须多输出一些字符,虽然使用现在比较优秀的IDE(Integrated Development Environment),不会给程序员的输入带来多少负责,但这些字符看起来还是有些多余。所以C++引入了namespace的概念,把一些标识符以命名空间树结构的方式组织起来,使代码看起来更优雅。而且事实证明,该特性是先进的,对于大型项目的作用是明显的,并且在后来的编程语言如Java、C#、Python都支持此类特性,只是有些叫法不同而已。
命名空间不仅可以用于组织类型(class、struct、Enum)等,还可以用于组织全局变量、全局函数等。如例程[2-1]所示,将不同模块的标识符分别组织到不同的命名空间中,从而避免标识符的冲突。
// 例程[2-1] #include <iostream> namespace sock{ typedef unsigned short socket_port_t; const char* LOOPBACK_ADDR = “127.0.0.1”; const socket_port_t DEFUALT_HTTP_PORT = 80; } int main( void ) { std::cout<<”Local HTTP addr = “<<sock::LOOPBACK_ADDR <<’:’<<sock::DEFUALT_HTTP_PORT<<std::endl; return 0; }
在大型的C++项目中使用命名空间比较好的项目如Google浏览器Chorme、开源C++库boost等,而没有使用命名空间的一个例子就是开源C++库ACE(The ADAPTIVE Communication Environment ),它选择了在每个类型的前面加上前缀“ACE_”,使得标识符都比较长,而且看起来有点儿冗余。为使用起来方便,而且不修改ACE的源码,可以使用typedef标识符对这些标识符进行重命名,如例程[2-2]所示。请注意,不能在这里使用#define,因为宏不受命名空间的限制。
// 例程[2-2] #include <ace/Mutex.h> namespace ace{ typedef ACE_Mutex Mutex; typedef ACE_Lock Lock; }
1.1.2. 如何引用命令空间内的标识符
当引用的标识符不在当前命名空间或全局命名空间内时,有三种方式可以引用该标识符,如引用前一节新定义的ace命令空间中的Mutex类型:
// 方式一 ace::Mutex mutex; // 方式二 using ace::Mutex; Mutex mutex; // 方式三 using namespace ace; Mutex mutex;
方式一只在必要的时候通过域运算符“::”引用指定命令空间内的标识符,适用于当前编译单元引用ace内的标识符不多,而且编译单元内使用这些标识符的次数也不多的情况。
方式二只引入ace::Mutex一个标识符,如果在当前编译单元内使用ace::Mutex次数较多,而且不会与当前命名空间内的标识符冲突,建议使用这种方式。
方式三是把ace命名空间中的全部标识符都引入到当前命名空间中,此后ace所有的标识符对于当前命名空间都是可见的,这会提高标识符冲突的危险。如果当前编译单元用到ace命令空间内的标识符较多,而且不会出现标识符冲突的问题,可以使用这种方式,以减少字符的输入。
对于以上三种方式,建议优先选择第一种,这种方式最不容易产生标识符冲突,方式二次之,尽可能不用第三种试,即使是对于C++标准库也不要使用第三种方式,因为至少在Solaris系统中就有一个struct类型叫map ??,如果你引用了包含该类型的头文件就会导致命名冲突。
另外,建议不要在头文件中使用using语句引入标识符,否则这些标识符将被暴露到引用这个头文件的所有编译单元内,这样很容易使命名空间失去其作用而产生命名冲突。
对于用到的系统API,建议函数名前使用域运算符加以区别,使程序可读性更好,如:::GetLastError( ), ::getcwd( )。
注意,切忌在自定义的命名空间中引用系统头文件,如例程[2-3]所示,避免造成标识符的混乱。
// 例程[2-3] namespace my_space{ #include <net/if.h> }
1.1.3. 命令空间的别名
当要引用的命名空间比较长,而且想用第一种方式引用命名空间内的实体,则可以通过命名空间别名,为原来的命名空间起个简短的名字,如例程[2-4]。
// 例程[2-4] namespace long_namespace{ void func( void ) { /* function body */ } } namespace ns = long_namespace; int main( void ) { ns::func(); return 0; }
1.1.4. 匿名命令空间
当声明命名空间时的名称为空时,则该命名空间为匿名命名空间(unnamed namespace)。匿名的空间是C++用于替代使用static定义作用域为本编译单元的全局函数或全局变量的一种新的替代方式,匿名空间与命名的命名空间一样可以嵌套。由于匿名命名空间没有命名空间的名字,所以也无法在其它的编译单元内通过extern声明该变量,于是该变量自然也只在本编译单元内可见,如例程[2-5]。
// 例程[2-5] #include <iostream> using namespace std; namespace{ int i = 256; } namespace ns{ namespace { int i = 128; } void func(void) { cout<<"ns::func :" <<endl; cout<<"\t::i="<<::i<<endl; cout<<"\tns::i="<<i<<endl; } } int main(void ) { cout<<::i<<endl; cout<<"i="<<i<<endl; cout<<"ns::i="<<ns::i<<endl; ns::func(); return 0; }
使用匿名空间比使用static至少有两个好处:
1) 对于一组多个标识符函数只需要使用一个匿名空间来声明,不需要多次输入static。
2) 可以嵌套。这样可以在不同命名空间中使用多个同名的标识符。
在C++的标准中也建议使用匿名命名空间间定义编译单元内部的全局变量,替代static,static关键词在此处被认为是过期的(deprecated)特性。
-
C++命名空间:默认命名空间与匿名命名空间
2021-01-17 10:10:443.C++默认命名空间 (1)又叫全局命名空间 (2)默认命名空间引用其他命名空间方法 (3)默认命名空间引用自己的方法 ...1.3.4.2、匿名命名空间的定义和使用 (1)定义 (2)匿名命名空间中引用其他命名空间中的方法 (3C++命名空间:默认命名空间与匿名命名空间
1.默认命名空间
1.1 默认命名空间的定义
默认命名空间也叫全局命名空间,所有没有置于某一具体命名空间下的代码即在默认命名空间下,例如
func()
,main()
函数。#include<iostream> void func(void); int main(int argc,char**argv) { std::cout<<"this is main"<<std::endl; return 0; } void func(void) { std::cout<<"this is func"<<std::endl; }
需要注意的是:
- 1.默认命名空间也是命名空间。
- 2.默认命名空间是全局的。
- 3.
main()
函数必须置于默认命名空间下。
1.2 默认命名空间引用其他命名空间
默认命名空间引用其他命名空间的方法与上一篇中的使用命名空间的方法是一样的,这里不再多说了。
1.3 默认命名空间引用自己
这个就是类似于C语言里简单的没有命名空间的函数调用,如下面的代码中
main()
调用func1()
:#include<iostream> void func1(void); int main(int argc,char**argv) { func1(); return 0; } void func1(void) { std::cout<<"this is func1"<<std::endl; }
1.4 其他命名空间引用默认命名空间
其他命名空间引用默认命名空间同样使用
::
,但是前面命名空间的名字是空白的,例如下面的代码中命名空间ns
引用默认命名空间下的func()
:#include<iostream> void func1(void); namespace ns { void func2(void) { ::func1(); } } int main(int argc,char**argv) { ns::func2(); return 0; } void func1(void) { std::cout<<"this is ::func1"<<std::endl; }
2.匿名命名空间
2.1 匿名命名空间的定义
匿名命名空间和全局命名空间有些类似,他们都没有名字,但是全局命名空间不需要自己定义,而匿名命名空间需要自己去定义,方法就是
namespace
后面没有空间名,直接就是{}
:namespace { void func(void) { std::cout<<"来自匿名命名空间的func()."<<std::endl; } }
2.2 匿名命名空间中引用其他命名空间
匿名命名空间引用其他命名空间的方法与上一篇中的使用命名空间的方法是一样的,这里不再多说了。
2.3 匿名命名空间中引用自己
直接用,无需添加命名空间名前缀,只要确保先声明后使用的顺序就没有问题。
2.4 其他命名空间中引用匿名命名空间
一般匿名命名空间定义于文件前面,类似于全局函数位置,之后的命名空间可以正常访问匿名命名空间中的内容,但是匿名命名空间的作用不在于此,而是在于跨文件访问的时候。因此其实对于单个文件内部,使用匿名命名空间与全局函数并无多大差别。
2.5 匿名命名空间的意义
- 1.匿名命名空间中的符号限于文件内部使用,不需要被外部引用。
- 2.匿名命名空间效果类似于全局变量和函数加
static
,但是比C
中的static
使用范围广,static
只能用于修饰函数名变量名,而不能用于修饰一个类型,如struct
,class
,而匿名命名空间则不局限于这些。 - 3.匿名命名空间虽然是一种特殊情况,但是用法逻辑上符合整个命名空间的一般原则。
-
c++系列:匿名命名空间
2021-01-02 08:14:003.实验3.1在匿名空间中引用其它命名空间3.2匿名命名空间中引用自己命名空间中的方法3.3其他命名空间中引用匿名命名空间中的方法3.4不同文件调用匿名命名空间4.最后 1.什么是匿名命名空间? 匿名命名空间就是一个没有...文章目录
1.什么是匿名命名空间?
匿名命名空间就是一个
没有名字
的命名空间。namespace { func() { ... } }
2.匿名命名空间有什么用处?
- 匿名命名空间里的内容只能被本文件调用,不能被外部引用;
- 匿名命名空间中的变量特点跟全局变量一样,而函数特点像是添加了static的功能一样。两者仅此在本文件使用
3.实验
3.1在匿名空间中引用其它命名空间
#include <iostream> using namespace std; namespace np { void func1() { cout << "this is func1" << endl; } } namespace { void func2() { np::func1(); } } int main() { func2(); return 0; }
实验结果
3.2匿名命名空间中引用自己命名空间中的方法
#include <iostream> using namespace std; namespace { int cnt = 0; void func2() { cout << "this is func2" << endl; } } int main() { cnt += 1; //像全局变量一样读取 cout << cnt << endl; func2(); //像全局变量一样读取 return 0; }
实验结果
3.3其他命名空间中引用匿名命名空间中的方法
#include <iostream> using namespace std; namespace { void func2() { cout << "this is func2" << endl; } } namespace np { void func1() { func2(); } } int main() { np::func1(); return 0; }
实验结果
3.4不同文件调用匿名命名空间
//test2.cpp //namespace xxx {extern func1()}; //连名字符号都没有,无法声明.... void func1() { func2(); }
test1.cpp #include <iostream> void func1(); using namespace std; namespace { void func2() { cout << "this is func2" << endl; } } int main() { func1(); return 0; }
实验结果
首先,匿名命名空间没有名字,或者说把名字给隐藏了,无法像xxx::func2()
这样子调用,并且在test2.cpp中也无法声明匿名命名空间空间(不符合语法)。4.最后
匿名命名空间的本质是什么?
就是将命名空间的名字符号给去掉,让其他文件找不到。
C++ 新的标准中提倡使用匿名命名空间,而不推荐使用static,因为static用在不同的地方,涵义不同,容易造成混淆.另外,static不能修饰class。 -
C++匿名命名空间的作用
2022-04-12 10:32:23C++学习笔记:默认命名空间与匿名命名空间 - it610.com -
匿名命名空间和 static 声明的区别
2021-11-14 21:28:06static关键字声 明的符号有内部链接属性,而匿名命名空间中声明的符号有外部链接属性。 二、static C和C++中每一个源文件(.c, .cpp)都可以单独编译成一个目标文件(.o),之后通过链接器把这些目标文件链接起来,... -
Qt命名空间 Qt namespace
2021-01-18 20:21:43讲述Qt命名空间怎么用,文章地址:https://lizhifun.blog.csdn.net/article/details/112584777 -
命名空间及匿名命名空间
2013-10-10 10:44:111. 使用命名空间的必要性 在一个大的项目中,当多时合作时,多个人编写的库头文件中,不可以避免的存在变量名相同的冲突,特别都是作为全局变量存在的时候,这种冲突就更为明显,如何解决这种冲突?方法就是使用... -
C++中的namespace命名空间和匿名命名空间
2020-08-08 17:21:50namespace叫命名空间,用于解决函数/变量重名的问题,如果一个函数/变量被声明在命名空间中,那么使用他们的时候需要加上作用域 namespace foo{ int x = 10; } cout<<foo::x<<endl; 除了加上作用... -
C++学习(十)匿名命名空间
2019-06-05 06:44:26由于匿名命名空间没有命名空间的名字,所以也无法在其它的编译单元内通过extern声明该变量,于是该变量自然也只在本编译单元内可见。 当定义一个命名空间时,可以忽略这个命名空间的名称: namespce { char c; ... -
c++ 匿名命名空间与static全局变量
2019-11-15 10:56:57https://www.cnblogs.com/youxin/p/4308364.htmlhttps://blog.csdn.net/Solstice/article/details/6186978 -
匿名命名空间 与 static 区别与联系
2018-01-22 20:24:08区别 1 static 无法修饰 ADT类型(自定义...匿名命名空间 1.匿名命名空间内的变量与函数,只在当前源文件内有效。同一源文件内的匿名空间中的符合最终会合并。 2.不同源文件的匿名命名空间,可以存在同名符 -
C++嵌套和匿名的命名空间namspace
2018-06-13 20:34:35嵌套的命名空间其作用是改进库中代码的组织架构,防止库中命名冲突::name 表示访问最外层的命名结构(包含自己所在最外层结构)省略::表示访问自身命名结构中的内容如下例所示:#include <stdlib.h> #... -
嵌套的命名空间和匿名的命名空间
2018-07-26 11:55:181. 嵌套的命名空间 命名空间可以嵌套,嵌套的命名空间可以进一步改进库中代码的组织。 namespace cplusplus_primer { namespace QueryLib { class Query { /* … */ }; // … } namespace Bookstore { ... -
解决C++重定义问题--匿名命名空间
2019-10-30 17:47:56今天遇到一个命名空间重定义的问题,程序框架大体如下: interface中定义的是一个namespace, 形式如下: namespade np { int a = 1; int b = 2; }; 并且三个module(1,2,3),以及core模块全都需要引用这个命名... -
c++命名空间
2021-11-07 10:16:42命名空间的由来 命名空间(namespace),是c++引入的一种机制,namespace目的是用来解决全局变量名与函数名或函数名与函数名之间名称相同的冲突的。c语言没有namespace,从c扩展而来的c++早期也没有,后来的c++、... -
理运用命名空间让js不产生冲突避免全局变量的泛滥
2021-01-19 20:01:48在不同的匿名函数中,根据功能声明一个不同的命名空间,每个匿名函数中GLOBAL对象的属性都不直接挂在GLOBAL上,而是挂在次匿名函数的命名空间下,如: 代码如下: [removed] var GLOBAL={} [removed] [removed] ... -
javascript自执行函数之伪命名空间封装法
2020-12-10 11:56:31下面的代码在window对象中创建一个命名空间 mySpace,并把自执行函数中的方法封装在mySpace命名空间之下,以便于我们调用这个自执行函数中的一些功能。 代码如下: (function() { //根据id获取对象 function $(id) {... -
c++命名空间的跨文件使用
2022-04-21 01:16:55命名空间的使用: 1、告诉编译器使用那个空间中的变量 如:xy::a = 100; 2、把整个命名空间暴露出来(整个空间内的内容可以直接访问) 如:using namespace xy 3、只暴露空间中某一成员 如:using xy::a 静态... -
c++ 匿名命名空间
2013-07-08 17:50:22当定义一个命名空间时,可以忽略这个命名空间的名称: ... 编译器在内部会为这个命名空间生成一个唯一的名字,而且还会为这个匿名的命名空间生成一条using指令。所以上面的代码在效果上等同于: na -
K8S命名空间
2020-05-25 22:16:531、简介Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。这些虚拟集群被称为命名空间。2、如何使用命名空间命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有... -
C++ 双冒号以及命名空间
2022-03-20 13:08:442.2 匿名命名空间 匿名命名空间是一个需要显式声明但是没有名字的命名空间,声明方式如下 namespace{ 匿名命名空间内的各种声明 } 匿名命名空间常被用来屏蔽不希望暴露给其他源文件的标识符。因为每个源文件的匿名... -
匿名空间的使用
2015-02-10 17:19:51编译器在内部会为这个命名空间生成一个唯一的名字,而且还会为这个匿名的命名空间生成一条using指令。所以上面的代码在效果上等同于: namespace __UNIQUE_NAME_ { char c; int i; double d; } us