C++之命名空间

目录

为什么要使用命名空间

什么是命名空间?

命名空间的使用方式

using编译指令

作用域限定符

using声明机制

命名空间的嵌套及覆盖

对命名空间的思考和总结


为什么要使用命名空间

一个大型的工程往往是由若干个人独立完成的,不同的人分别完成不同的部分,最后再组合成一个完整的程序。由于各个头文件是由不同的人设计的,有可能在不同的头文件中用了相同的名字来命名所定义的类或函数,这样在程序中就会出现名字冲突。不仅如此,有可能我们自己定义的名字会与C++库中的名字发生冲突。
名字冲突就是在同一个作用域中有两个或多个同名的实体,为了解决命名冲突 ,C++中引入了命名空间,所谓命名空间就是一个可以由用户自己定义的作用域,在不同的作用域中可以定义相同名字的变量,互不干扰,系统能够区分它们。

什么是命名空间?

命名空间又称为名字空间,是程序员命名的内存区域,程序员根据需要指定一些有名字的空间域,把一些全局实体分别存放到各个命名空间中,从而与其他全局实体分隔开。通俗的说,每个名字空间都是一个名字空间域,存放在名字空间域中的全局实体只在本空间域内有效。名字空间对全局实体加以域的限制,从而合理的解决命名冲突。

C++中定义命名空间的基本格式如下:

namespace wd
{
int val1 = 0;
char val2;
}// end of namespace wd

在声明一个命名空间时,大括号内不仅可以存放变量,还可以存放以下类型:
变量,常量,函数(可以是定义或声明),结构体,类,模板,命名空间(可以嵌套定义)

namespace wd
{
 int number = 0;
 struct Foo
{
   char ch;
   int val;
};
 void display();
}// end of namespace wd

定义在命名空间中的变量或者函数都称为实体,名称空间中的实体作用域是全局的, 并不意味着其可见域是全局的。
如果不使用作用域限定符和using机制,抛开名称空间嵌套和内部屏蔽的情况,实体的可见域是从实体创建到该名称空间结束。
在命名空间外,该实体是不可见的。

命名空间的使用方式

名空间一共有三种使用方式,分别是using编译指令、作用域限定符、using声明机制。

using编译指令

我们接触的第一个C++程序基本上都是这样的,其中std代表的是标准命名空间。

#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << "hell,world" << endl; 
  return 0;
}

其中第二行就使用了using编译指令。如果一个名称空间中有多个实体,使用using编译指令,就会把该空间中的所有实体一次性引入到程序之中;对于初学者来说,如果对一个命名空间中的实体并不熟悉时,直接使用这种方式,有可能还是会造成名字冲突的问题,而且出现错误之后,还不好查找错误的原因,比如下面的程序就会报错,当然该错误是人为造成的。

#include <iostream>
using namespace std;
double cout()
{
  return 1.1;
}
int main(void)
{
  cout();
  return 0;
}

作用域限定符

第二种方式就是直接使用作用域限定符::啦。每次要使用某个名称空间中的实体时,都直接加上,例如:

namespace wd
{
int number = 10;
void display()
{
  //cout,endl都是std空间中的实体,所以都加上'std::'命名空间
  std::cout << "wd::display()" << std::endl;
}
}//end of namespace wd
int main(void)
{
  std::cout << "wd::number = " << wd::number << endl;
  wd::display();
}

这种方式会显得比较冗余,所以还可以采用第三种使用方式。

using声明机制

using声明机制的作用域是从using语句开始,到using所在的作用域结束。要注意,在同一作用域内用using声明的不同的命名空间的成员不能有同名的成员,否则会发生重定义。

#include <iostream>
using std::cout;
using std::endl;
namespace wd
{
int number = 10;
void display()
{
cout << "wd::display()" << endl;
}
}//end of namespace wd
using wd::number;
using wd::display;
int main(void)
{
  cout << "wd::number = " << number << endl;
  wd::display();
}

在这三种方式之中,推荐使用的就是第三种,需要哪个实体的时候就引入到程序中,不需要的实体就不引入,尽可能减小犯错误的概率。

命名空间的嵌套及覆盖

int number = 1;
namespace wd
{
int number = 10;
namespace wh
{
int number = 100;
void display()
{
  cout << "wd::wh::display()" << endl;
}
}//end of namespace wh
 
void display(int number)
{
  cout << "形参number = " << number << endl;
  cout << "wd命名空间中的number = " << wd::number << endl;
  cout << "wh命名空间中的number = " << wd::wh::number << endl;
}
 
}//end of namespace wd
int main(void)
{
  using wd::display;
  display();
  return 0;
}

对命名空间的思考和总结

下面引用当前流行的名称空间使用指导原则:
提倡在已命名的名称空间中定义变量,而不是直接定义外部全局变量或者静态全局变量。
如果开发了一个函数库或者类库,提倡将其放在一个名称空间中
对于using 声明,首先将其作用域设置为局部而不是全局
不要在头文件中使用using编译指令,这样,使得可用名称变得模糊,容易出现二义性,
包含头文件的顺序可能会影响程序的行为,如果非要使用using编译指令,建议放在所有#include预编译指令后。

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~|Bernard|

你的鼓励是我写下去最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值