C++命名空间:命名空间基础

1. 何为命名空间

1.1 什么是命名空间

namespace,中文就是命名空间,同时这也是C++语言中的一个关键字。命名空间是C++引入的一种彻底地、很方便地解决全局变量和函数名冲突的机制。变量分全局变量和局部变量,所谓全局,就是定义在函数之外的,局部变量则一般定义在函数体内部。函数则全部是全局性质的。

C语言没有命名空间,但是C++及之后的JavaPython等高级语言都有,并且在C++的基础上有更好的改进。

理解命名空间的关键点有2个:

  • 1.命名空间是如何解决名称冲突的。
  • 2.使用了命名空间后如何合法地访问变量。

1.2 C语言是如何解决名称冲突的

首先要知道,名称冲突是一个客观存在。在大型的C语言项目(比如Linux内核)中会有很多C文件,全局变量和函数都是extern链接属性(其他文件可以通过声明来跨文件访问),一个项目是一个单体程序,项目中的全局变量和函数理应能互相访问,因此很容易发生名称冲突。

C语言中解决名称冲突的办法是:

  • 1.同一个C文件不要太大,由一个人写。
  • 2.每个C文件(或几个C文件构成的一个模块)中所有全局变量和函数前加统一的唯一前缀。比如写SD卡模块的函数名都叫sd_func(),写串口模块的都叫uart_func()
  • 3.不需要文件外访问的全局变量和函数前面都加staticstatic修饰全局变量和函数的作用就是将该变量和函数的可见范围从externallocal,即仅本文件内可见,其他文件不可访问。

C语言的这种解决命名冲突的方案是可行的,不然不会有Linux内核这样大的项目,并且C++早期就是这样做的,但这种方法太生硬,没有从语言本身去解决问题,显得不够美观。

1.3 命名空间如何解决问题

为了实现命名空间机制,C++引入namespace关键字,定义命名空间的语法为:

namespace xx
{
	...
};

命名空间本质上其实是对全局变量和函数在一定范围内链接属性的更改和控制,尖括号{}内就是命名空间的范围。一个特定名称的namespace,比如上面的xx,一对大括号内部定义的变量、函数、类等均属于该命名空间内。

在命名空间内部互相引用时可以直接使用变量名、函数名等,跨命名空间互相引用时必须同时指定被引用方的命名空间名和变量名、函数名才可以找到,因此其实命名空间看起来就好像是给这个变量名、函数名添加了一种前缀。

1.4 关于语言特性的思考

语言特性是语言通过关键字或符号所支持、所引入的一种功能特性,如namespacetemplate运算符重载等。语言特性必定对应解决某种问题,必定在某方面对程序员有帮助,是有了某个问题不好解决才需要引入一种语言特性或者说机制来解决这个问题。

语言特性越多或者设计越复杂,则语言本身就越难使用,但语言就越厉害,C++就是这样的一种语言。语言特性体现为某种语法,本质上靠编译工具链(预处理器、编译器、链接器等)提供支持,C++11/14/17/20的版本变迁,无非是新增或修正某些细节语言特性。就事论事讨论编程语言,其实难点都在掌握和熟练运用语言特性上。

2.namespace的初级定义和使用

2.1 同一文件内定义namespace

#include<iostream>
using namespace std;

namespace test{
int a;
float b;
void test_func(void){
	cout<<"test_func"<<endl;
}
};

2.2 同一文件内使用namespace

namespace有三种引用方法。

方式一:不做任何声明直接使用,类似于添加前缀,::叫做作用于解析符,左边是命名空间的名字,右边是该空间内的变量或函数名。这样编译器就会知道你要用的是test命名空间中的变量a以及函数test_func()

int main(int argc,char**argv)
{
	test::a;
	test::test_func();
	return 0;
}

方式二:通过using告诉编译器去test空间中寻找test_func来使用。

//声明test_func可以到test中找
using test::test_func();

//使用test_func
int main(int argc,char**argv)
{
	test_func();
	return 0;
}

方式三:直接声明命名空间,则该命名空间下的变量函数可以直接使用。

using namespace test;

int main(int argc,char**argv)
{
	test_func();
	return 0;
}

2.3 不同cpp文件间定义和使用namespace

在文件1中定义的变量和函数是可以在另一个文件2中被使用的,关键是如何在文件2中声明。规范的方法应该是同时写一个test1.hpp,即头文件,在头文件中写入命名空间以及命名空间内的函数声明,在.cpp文件中写函数的实现,然后在调用该函数的源文件中包含该头文件。

test1.hpp:

#ifndef TEST1_H
#define TEST1_H

namespace test1
{
	void func_1();
};

#endif

test1.cpp

#include"test1.hpp"
#include<iostream>

void test1::func_1()
{
	std::cout<<"this is test1 func1"<<std::endl;
}

test2.cpp

#include"test1.hpp"

using namespace test1;

int main(int argc,char**argv)
{
	func_1();
	return 0;
}

编译命令:

g++ test2.cpp test1.cpp 
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值