catalog
- 内嵌
- enum/class/namespace命名冲突
- 多个同名namespace的原理
- 开头::
-
- 规范写法
- 作用域
- Base
-
内嵌
c++17
后, 支持: namespace A::B::C{ }
写法
enum/class/namespace命名冲突
namespace A {}
class B {}
enum C {}
A B C
这3个名称, 必须相互都不同!!! 否则就产生冲突.
因为, AC的使用方式, 都是: A:: 和 C::
. B的static 也是B::
方式.
此时, 有一个 (同名)的 变量/函数 int D
, 这个D 和 (ABC) 重名, 是不会冲突的!!!
因为, AC
的使用方式 都是: A:: C::
, B的使用方式是: B obj; 或 B::
, 这都是和 (变量/函数) 不同.
多个同名namespace的原理
namespace AA{
int a;
}
namespace BB{
using ::AA::a;
}
namespace BB{
int b = a; ' 这是可以的; 上面的(using ::AA::a), 会继承下来 '
}
namespace NS{
int a = 123;
}
namespace NS {
int b = a;
}
其实, 你应该把它想象为: 代码合并
namespace NS{
int a = 123;
int b = a;
}
即: 多个同名namespace域, 其实就相当于: 自上而下的 代码合并
开头::
变量/函数前
int a = 1;
{
int a = 2;
' 此时, 使用a, 会使用到2; 如果要使用1, 则是 ::a '
' ::a 是(强制)使用 全局域的东西. 比如你没有int a = 1, 使用::a时, 是会报错的!!! 并不会使用a=2这个 '
}
------
namespace ST{
int a;
}
{
using namespace ST;
::a; ' 这是会报错的!!! '
' ::a不受命名空间的影响, ::a中的a 一定是全局域的(外面没有命名空间) '
}
即, ::a, ::func()
一定是说明: a 和 func()
是全局域的.
命名空间前
在阅读一些官方文档时, 常看到: ::std::cout << "...";
这种写法
为什么要在命名空间前 加一个::
呢? 直接写std::cout
不行吗??
namespace std{
data = 123;
}
namespace my{
namespace std{
data = 456;
}
}
{
using namespace my;
std::data; ' 此时, 会使用456. '
::std::data; ' 使用123. 即::std, 说明这个std是全局的命名空间, 不受using namespace的影响 '
}
所以, 要使用 全局的东西变量 / 函数 / 命名空间
, 最好前面都加上::
规范写法
我们要研究,namespace的规范写法: 就首先应该区别 他和class里的static有何区别??
看似,他俩好像的功能差不多。
namespace 和 class里的static,最大的区别是:
class通常写在.h头文件里
而且,class和const/static一样,是相对本文件的'局部'量
意味着: 每个cpp里的,虽然都是#include同个头文件
但最终,每个cpp里的 都是不同的!!!
并不是真正意义上的: 全体文件共用
而namespace他就是全体文件共用!!
namespace就是这样,你完全可以将namespace去掉!!
即,你就看他里面的东西即可 (完全不受namespace的影响!! )
所有,通常namespace的用法:
1.h头文件里:
namespace SP{ ' 写声明 '
extern int xx;
extern void xx();
}
在某一个cpp里,实现每个: SP::xx
1.cpp、2.cpp、3.cpp等里: #include "1.h" 即可
' 你把namespace 改成 class+static的方式, 可以达到相同的效果 '
' 但,会带来不必要的消耗!!! 因为,class是相对本cpp文件的!! '
' class 和 const/static变量一样, 并不是全体文件共用的!!! '
作用域
namespace的作用域是' 所有cpp文件 ',而不是'当前文件'
'我们知道,class ST{..}、static、const的作用域是当前文件 '
' 1.cpp里: '
int G_A = 123;
namespace SP{
int sp_a = 456;
}
' 2.cpp里:'
namespace SP{
extern int sp_a; ' 引用: 1.cpp里的SP::sp_a '
}
如果你要在2.cpp的SP里面,使用G_A这个变量!!
比如: namespace SP{ int sp_b = G_A; }
首先,你肯定需要引用G_A这个变量; 即需要extern int G_A;这句代码
' 这句话,你不可以写到SP里面!!! '
即2.cpp:
extern int G_A; ' 不可以写到SP里面 '
namespace SP{
extern int sp_a; ' 以至于: 2.cpp可以使用1.cpp里的SP::sp_a=456 '
int sp_b = G_A; ' 使用2.cpp里的G_A全局变量 '
}
' 即,你在namespace SP写的: extern int A; '
' 表示: 在其他cpp文件的namespace SP{..}里找 '
' 有没有int A这个变量的定义!!! '
' 他并不会在 其他cpp的全局域里找,而是在SP域里找! '
---------------------------------------------------------
namespace SP{
void func();
}
void SP::func(){ ... }
' 有点类似于, 类的实现 '
' 但这种写法没有应用性 '
Base
namespace XX{ ... };
' 必须写在“全局”里,他是解决: 你需要定义2个“全局变量A/函数FF”冲突的问题 '
' namespace是对:“全局变量”,即堆空间 进行“命名”划分区域而已 '
int A = 123;
void FF(){ ... }
namespace NAMESPACE{
int A = 456; ' 这2个A变量, 和2个FF函数。 不冲突!!! '
void FF(){ ... }
void xx(){
A; ' 优先使用NAMESPACE里的, 其次是全局的。 '
}
}
{
namespace TT = NAMESPACE; / 起别名, TT的生命期,就在这个{}作用域里。
DE( TT::A );
using namespace NAMESPACE; / 你直接写A即可。 他的作用域 也是在{}里
DE( A ); '===注意,此时如果“全局有int A” 同时 “namespace里也有int A'
' 是会报错的!!! 因为确实不知道,你要的是哪个!!!'
' 所以,如果使用using namespace XX; '
' 你必须保证: 你XX里的所有变量/函数,和 你的全局的变量/函数,没有重名的'
' 因为,本来 按规范的来,应该是: NAMESPACE::A来使用。'
}
定义顺序
namespace ST{
void f1(){ f2(); }
void f2(){ .... }
}
' 这样是会报错的!!! 因为到f1时,f2()还没有实现出来 '
' 所以,在写namespace时,几乎你就把他当成没有,当成正常的全局函数 '
处理:
namespace ST{
extern void f1(); ' extern可以不写 '
extern void f2();
}
void ST::f1(){ f2(); }
void ST::f2(){ }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)