写点什么

C++ 命名空间:别再因为命名冲突而烦恼了。

作者:子夜的星
  • 2023-01-28
    河南
  • 本文字数:2299 字

    阅读完需:约 8 分钟

C++命名空间:别再因为命名冲突而烦恼了。

一、前言

实际的软件开发过程中,一个程序往往由多名程序员共同开发。不同程序员在开发过程中都会使用大量的变量和函数,这个时候就会出现变量或函数的命名冲突。虽然每个人的代码都没有问题,但将它们结合到一起就可能会因为命名冲突而出现错误。


在没有命名空间的 C 语言中,如果出现了命名冲突,那只能在所有人写过的代码中,找出那些命名冲突的变量或函数,进行修改。


因为李四经常写出和张三相同的变量名和函数名,没少挨张三的打。公司为了李四的生命安全着想,决定让他们一起学习有命名空间(namespace)C++




二、命名空间

1、命名空间的定义

C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,它可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上,命名空间就是定义了一个范围,命名空间中的所有内容都会局限于该命名空间这个范围之中。


定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。

Ⅰ、正常定

namespace name1{  // 命名空间中可以定义变量/函数/类型  int rand = 10;  int Add(int left, int right)  {    return left + right;  }    struct Node  {    struct Node* next;    int val;  };}
复制代码


这段代码中name1是该命名空间的名字,它里面可以包含变量、函数、类、typedef#define 等,最后用{ }包围起来。

Ⅱ、嵌套定义

命名空间是可以嵌套定义的,即在一个命名空间中定义另外一个命名空间。


namespace name1{int a;int b;int Add(int left, int right) {     return left + right; }namespace name2 {     int c;     int d;     int Sub(int left, int right)     {         return left - right;     } }}
复制代码

Ⅲ、不连续定义

同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。在test.h中有如下定义:


namespace name3{    int Add(int x, int y)    {        return x + y;    }}
复制代码


test.cpp中有如下定义:


namespace name3{    int Mul(int left, int right)    {        return left * right;    }}
复制代码


由于两个命名空间的名字相同,所以在编译器严重,这两段可以视为如下代码:


namespace name3{    int Add(int x, int y)    {        return x + y;    }    int Mul(int left, int right)    {        return left * right;    }}
复制代码

2、命名空间的使用

命名空间的使用有如下三种方式:


  • 加命名空间名称及域解析操作符

  • 使用using将命名空间中某个成员引入

  • 使用using namespace命名空间名称 引入

Ⅰ、域解析操作符

::是一个新符号,称为域解析操作符,在C++中用来指明要使用的命名空间。


namespace name1{int a = 1;int b = 2;int Add(int left, int right) {     return left + right; }}int main(){    printf("%d\n", name1::a); //使用name1中的变量a    return 0;    }
复制代码

Ⅱ、using引入空间成员

使用using这个新关键字引入空间中的成员。


namespace name1{int a = 1;int b = 2;int Add(int left, int right) {     return left + right; }}using name1::b;//引入了name1命名空间中的b成员int main(){    printf("%d\n", name1::a);    printf("%d\n", b);    return 0;    }
复制代码

Ⅲ、using namespace引入空间所有成员

namespace name1{    int a = 1;    int b = 2;    int Add(int left, int right)    {        return left + right;    }}using namespace name1;int main(){    printf("%d\n", a);    printf("%d\n", b);    Add(10, 20);    return 0;}
复制代码


三、std命名空间

1、std 的来历

std是英文单词 S tan dard 的缩写,意思是“标准命名空间”。


它是 C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中。


因为早期的 C++ 还不完善,不支持命名空间,没有自己的编译器,而是将 C++ 代码翻译成 C 代码,再通过 C 编译器完成编译。所以早期标准库将所有功能在全局域中实现,声明在.h 后缀的头文件中,使用时只需包含对应头文件即可,后来又开发了命名空间这一功能,就将类、函数、宏等都统一纳入在std命名空间下,为了和 C 的头文件区分,也为了正确使用命名空间。


注意:为了避免头文件重名,C++ 库也对头文件的命名做了调整,去掉了后缀.h,所以 C 语言的头文件,在 c++中依旧存在,但在每个名字前还要添加一个 c 字母,并且去掉.h 所以 C 语言的stdio.h变成了cstdiostdlib.h变成了cstdlib。比如 C 语言中我们使用printf函数需要这样写:


#include<stdio.h>int main (){  printf("hello world !");  return 0;}
复制代码


而 C++中我们使用printf函数则需要这样写:


#include<cstdio>using namespace std;int main(){  printf("hello world !");  return 0;}
复制代码

2、std的使用惯例

  1. 在日常练习中,建议直接using namespace std即可,这样就很方便。

  2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 +using std::cout展开常用的库对象/类型等方式。

四、总结

1、命名空间的三种定义方式

  • 正常定义。

  • 嵌套定义。

  • 不连续定义。

2、命名空间的三种使用方法

  • 域解析操作符::

  • using关键字部分引入。

  • using namespace全部引入。

3、 std使用注意

  • 区分日常使用和项目开发使用。

发布于: 刚刚阅读数: 3
用户头像

子夜的星

关注

还未添加个人签名 2022-02-02 加入

还未添加个人简介

评论

发布
暂无评论
C++命名空间:别再因为命名冲突而烦恼了。_c++_子夜的星_InfoQ写作社区