【C++】命名空间

简介: 【C++】命名空间

🎏命名空间的由来

在C++开发过程中,大型程序往往会使用多个独立开发的库,这些库又会定义大量的全局名字,如类,函数和模板等。当应用程序用到多个供应商提供的库时,不可避免地会发生某些名字相互冲突的情况。多个库将名字放置在全局命名空间中将引发命名空间污染(namespace pollution)。

如下情况,C语言是无法解决类似的冲突问题的:

#include<stdio.h>
#include<stdlib.h>
 
int rand = 10;
//rand是有关随机数的一个库函数
 
int main()
{
  printf("%d\n", rand);
 
  return 0;
}

如上代码在编译器中运行结果会有重定义错误:

传统上,程序员通过将其定义的全局实体名字设得很长来避免命名空间污染问题,这样的名字通常包含表示名字所属库的前缀部分:

class cplusplus_primer_Query{ ... };
string cplusplus_primer_make_plural(size_t,string&);

这种解决方案显然不太理想:对于程序员来说,书写和阅读这么长的名字费时费力且过于烦琐

命名空间(namespace)防止名字冲突提供了更加可控的机制。命名空间分割了全局命名空间,其中每个命名空间是一个作用域通过在某个命名空间中定义库的名字,库的作者(以及用户)可以避免全局名字固有的限制


🎏命名空间的定义

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

如下,我们定义了一个名为MFC的命名空间,里面包含了三个成员,分别是:变量min,函数Sum,结构体Stu:

namespace MFC
{
  //命名空间中可以定义变量/函数/类型
 
  int min = 1;
 
  int Sum(int a, int b)
  {
    return a + b;
  }
 
  struct Stu
  {
    struct Stu* next;
    char name[10];
  };
}

📌每个命名空间都是一个作用域

      和其他作用域类似,命名空间中的每个名字都必须表示该空间内的唯一实体。因为不同命名空间的作用域不同,所以在不同命名空间内可以有相同名字的成员。


📌命名空间是可以嵌套的

如下A2命名空间就嵌套在A1里:

//命名空间可以嵌套
namespace A1
{
  int a;
  int b;
  int Sum(int sum1, int sum2)
  {
    return sum1 + sum2;
  }
 
  namespace A2
  {
    int c;
    int d;
    int sub(int sub1, int sub2)
    {
      return sub1 - sub2;
    }
  }
}

📌命名空间可以是不连续的

命名空间可以定义在几个不同的部分,同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中:


🎏命名空间使用的三种方式

📌加命名空间名称及作用域限定符

这种命名空间的使用方式是仅在使用某个变量的时候去找到它存在的命名空间然后将它单独展开使用。

这种使用方式适合于只在程序中使用一两次的变量/函数/类型,这种使用方式可以有效防止命名空间大幅度展开造成的命名污染,但缺点是当该成员要使用多次时,每次都在使用时展开,会导致代码逻辑比较繁琐。

如下,这次展开的作用范围就仅仅在printf()函数中才有用:

namespace MFC
{
  //命名空间中可以定义变量/函数/类型
  int min = 1;
 
  int Sum(int a, int b)
  {
    return a + b;
  }
 
  struct Stu
  {
    struct Stu* next;
    char name[10];
  };
}
 
int main()
{
  printf("%d\n", MFC::min);
 
  return 0;
}

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

这种命名空间的使用方式是在全局范围将命名空间中的某个成员引入,此时,该变量在工程中就相当于一个全局变量,此时在整个工程中就可以直接使用该成员了.

这种是我们一般比较推荐的命名空间使用方式,因为它既不会像单独展开那样导致代码太过繁琐,又不会像命名空间全部展开那样导致大面积的命名污染.

如下,18行使用using展开的成员min就可以在主函数内直接使用了:

namespace MFC
{
  //命名空间中可以定义变量/函数/类型
  int min = 1;
 
  int Sum(int a, int b)
  {
    return a + b;
  }
 
  struct Stu
  {
    struct Stu* next;
    char name[10];
  };
}
 
using MFC::min;
 
int main()
{
  printf("%d\n", min);
 
  return 0;
}

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

这种命名空间的使用方式是在全局范围将整个命名空间引入。此时,该命名空间的所有成员都被引入到了工程中,此时在整个工程中就可以直接使用该命名空间的所有成员了.

这种方式会将命名空间里的所有成员都暴露在全局中,是我们最不推荐的一种使用方式,因为这样极易造成不经意间的命名空间污染问题.

如下,18行使用using namespace展开的命名空间MFC里的成员就可以在主函数内直接使用了:

namespace MFC
{
  //命名空间中可以定义变量/函数/类型
  int min = 1;
 
  int Sum(int a, int b)
  {
    return a + b;
  }
 
  struct Stu
  {
    struct Stu* next;
    char name[10];
  };
}
 
using namespace MFC;
 
int main()
{
  printf("%d\n", min);
  printf("%d\n", Sum(1, 2));
 
  return 0;
}

结语

希望这篇命名空间的简介能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C++】“Hello World!“

【C++】缺省参数(默认参数)



相关文章
|
2月前
|
编译器 C++
C++进阶之路:何为命名空间、缺省参数与函数重载
C++进阶之路:何为命名空间、缺省参数与函数重载
27 3
|
3月前
|
C++ 开发者
C++程序命名空间
C++程序命名空间
30 1
|
10天前
|
编译器 C语言 C++
C++入门 | 命名空间、输入输出、缺省参数
C++入门 | 命名空间、输入输出、缺省参数
25 4
|
28天前
|
安全 编译器 C++
C++一分钟之-C++中的属性命名空间
【7月更文挑战第22天】C++11引入属性作为元数据,虽无内置属性命名空间,但可通过自定义属性与命名空间组合实现类似效果。例如,创建`perf`命名空间存放`slow`和`fast`属性来标记函数性能。正确使用属性需注意位置、避免重复和确保与实现一致,以提升代码可读性和编译器理解。通过模拟属性命名空间,可以更有效地管理和使用属性。
35 1
|
1月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
1月前
|
C语言 C++ 开发者
C++基础知识(一:命名空间的各种使用方法)
C++在C的基础上引入了更多的元素,例如类,类的私密性要比C中的结构体更加优秀,引用,重载,命名空间,以及STL库,模板编程和更多的函数,在面向对象的编程上更加高效。C语言的优势则是更加底层,编译速度会更快,在编写内核时大多数都是C语言去写。 在C++中,命名空间(Namespace)是一种组织代码的方式,主要用于解决全局变量、函数或类的命名冲突问题。命名空间提供了一种封装机制,允许开发者将相关的类、函数、变量等放在一个逻辑上封闭的区域中,这样相同的名字在不同的命名空间中可以共存,而不会相互干扰。
|
2月前
|
C++
C++命名空间(namespace)的使用
C++命名空间(namespace)的使用
|
2月前
|
人工智能 安全 编译器
【C++入门】—— C++入门 (上)_命名空间
【C++入门】—— C++入门 (上)_命名空间
20 2
|
3月前
|
C++
C++中使用namespace关键字定义和访问命名空间的技术性探讨
C++中使用namespace关键字定义和访问命名空间的技术性探讨
24 3
|
2月前
|
Unix 编译器 C语言
【C++航海王:追寻罗杰的编程之路】关键字、命名空间、输入输出、缺省、重载汇总
【C++航海王:追寻罗杰的编程之路】关键字、命名空间、输入输出、缺省、重载汇总
17 0