C++学习 十二、内存模型,作用域,名称空间 (3)命名空间

前言

本篇继续C++学习记录,命名空间。

如果,某程序使用的两个开源库都定义了一个名为start()的函数,那么在main()函数中该如何调用某个库的start()函数呢?

C++通过命名空间被用于限制命名的作用域。

命名空间namespace

创建命名空间

关键字namespace用于创造一个命名空间,示例如下:

namespace mySpace1{
	int a;
	int b;
	void func(int);
}

namespace mySpace2{
	int a;
	int b;
	void func(int);
}

命名空间中可以存放变量,函数,结构,类,#define,typedef等等。不同命名空间的同名符号不会出现冲突。

可以随时把名称加入到一个命名空间中,在命名空间中的函数可以分开声明和定义:

namespace mySpace1{
	int d;
	void func(int x){
		cout << x << endl;
	}
}

注意:命名空间必须是全局的,或者被嵌套在另一个命名空间中。不能在函数中创建命名空间。

访问命名空间内成员

访问命名空间内的成员时,需要使用域名解析运算符::,示例如下:

void main(){
	mySpace1::a = 1;
	mySpace1::func(a);
}

全局命名空间

除了自己定义的命名空间外,文件本身自带了一个全局命名空间,全局定义的变量,函数,结构等都属于该文件的全局命名空间,可以通过::Name来调用全局名称,示例如下:

int varName = 1;

void func(){
	int varName = 2;
	cout << varName << endl; // 2
	cout << ::varName << endl; // 1
}

嵌套命名空间

可以在命名空间中创建命名空间:

namespace space1{
	namespace space2{
		int b;
	}
	int a;
}

分别使用space1::space2::b;,space1::a来使用变量。

命名空间别名

嵌套命名空间名字较长,可以给命名空间取别名:

void main(){
	namespace ss12 = space1::space2;
	ss12::a = 1;
}

注意:可以在函数中给命名空间取别名,但不能在函数中创建新命名空间。

无名命名空间

也可以定义没有名字的命名空间,示例如下:

namespace {
	int a;
	int b;
	void func(int);
}

无名命名空间因为没有名字,不能在其他文件中使用该空间中的名称。因此,无名namespace中的名称具有类似内部链接的性质,可以作为静态全局变量和静态函数的替代品。

关键字using

域名解析运算符::的使用比较繁琐(虽然我还是比较习惯直接用::),可以使用using关键字来进行简化。

using声明

using声明用于把命名空间中的名称添加到全局或者局部,示例如下:

namespace sp{
	int a;
	int b;
}

using sp::b;

void main(){
	using sp::a;
	// int a; //error
	a = 1;
	int b;
	b = 2;
	::b = 3;
}

上面这一段代码中,使用using声明后,就可以不指明命名空间解析sp::来调用命名空间中的ab

局部using声明将sp::a添加到main函数的局部代码块中,因此不能再在该局部声明同名变量了,否则将报error: redeclaration of 'int a'

全局using声明将sp::b添加到全局,main函数局部仍然可以声明一个同名变量,同时隐藏全局变量。

using编译指令

using编译指令的使用方法为using namespace spacename,使得命名空间中所有名称都在编译指令的位置区域可用,最常见的用法是使用标准命名空间std

void main(){
	using namespace std;
}

然后就能够直接使用std命名空间中的名称。

using声明与using编译指令

上面提到,using声明更类似于在全局或者局部声明了一个变量,因此在该位置不能再定义同名变量。

而using编译指令则不同,它更类似于使用作用域解析:

namespace space{
	int a;
	int b;
}

int b;

void main(){
	using namespace space;
	a = 1; // space::a
	// b = 1; // error!
	space::b = 1; // space::b
	::b = 2; // global b;
	int b;
	b = 3; // local b
}

上面的示例中,using编译指令使得space中的名称a可以直接在main()函数中使用。

对于b,由于定义了全局版本和命名空间版本,因此在main()函数中,直接使用名称b将报error: ambiguous reference 'b',也就是编译器分不清到底使用的是全局名称还是空间中的名称。

最后,使用using编译指令时,main()中还能再定义了一个局部b,使得全局、局部、局部空间版本的b共存。而使用using声明时,局部空间版本的b与局部b不能共存。

这也就是为什么说,using声明类似全局或局部声明,而using编译指令类似作用域解析。

注意:尽量直接使用作用域解析来使用命名空间里的名称。

命名空间规范

下面是一些命名空间使用的通用规范:

  • 尽量使用命名空间中的变量来替代全局变量、静态全局变量
  • 类库、函数库应当放在命名空间中
  • 不在头文件中使用using namespace指令
  • 尽量使用作用域解析方法使用空间内的名称

后记

本篇三章内容把C++的内存模型,作用域和命名空间记录完。

下篇就要进入C++的特色核心,类与对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值