【C++】命名空间

目录

1 命名空间的引入

2 命名空间的定义

3 标准命名空间std

头文件和std的关系

4 命名空间的使用

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

 4.2 使用using将命名空间中某个成员引入(最推荐)

4.3 使用using namespace +命名空间名称

5 总结


1 命名空间的引入

为了解决C语言中命名冲突问题,C++引入了命名空间:

【C++】命名空间_第1张图片

rand()函数包含在C语言头文件stdlib.h里,为了解决这个问题,可以这样做:

【C++】命名空间_第2张图片

2 命名空间的定义

命名空间里可以放任意的变量、函数、结构体等等

namespace space2
{
	int a = 10;
	
	int add(int x, int y)
	{
		return x + y;
	}

	struct ListNode
	{
		struct SListNode* next;
		int val;
	};
	//...
}

命名空间的嵌套 

namespace s3
{
	int a = 10;
	namespace s4
	{
		int a = 20;
	}
}

 命名空间s3和s4的变量a虽然同名,但并不会冲突!

命名空间的合并

#include
namespace s3
{
	int a = 10;
}

namespace s3
{
	int b = 20;
}

int main()
{
	std::cout << s3::b << std::endl;
    return 0;
}

上面的写法相当于:

namespace s3
{
	int a = 10;
	int b = 20;
}

【C++】命名空间_第3张图片

 std是C++的标准命名空间,::是作用域限定符,下面会详细介绍。

3 标准命名空间std

标准命名空间std是C++标准库中定义的命名空间,用于包含一系列标准库提供的类、函数和对象。它提供了一种组织和封装代码的机制,以避免命名冲突,并将相关的实体进行逻辑上的分组。在程序中使用std命名空间,可以方便地使用标准库中的函数、对象等。

比如C++的标准输入cin输出cout,STL中的vector、sort、queue、stack等等都在std命名空间里。

头文件和std的关系

先来看一个C++输出hello world的程序:

#include
using namespace std;//标准命名空间std展开

int main()
{
	cout << "Hello World" << endl;
	return 0;
}

其中,iostream文件的包含以及标准命名空间std的展开都是缺一不可的,为什么呢?

头文件和std命名空间的关系是,头文件中的内容被包含在std命名空间中。这意味着,如果一个头文件没有使用任何命名空间,那么其定义的所有符号都位于全局作用域;如果一个头文件使用了命名空间std,那么其定义的所有符号都位于std命名空间中。

在C++标准库中,许多常用的函数、对象和类都被定义在std命名空间中,例如std::coutstd::vector等。因此,在使用这些函数、对象或类时,需要使用std::前缀来标识它们属于std命名空间。

需要注意的是,虽然大部分编译器在实现时并没有严格遵循C++标准,对于原来C语言的头文件,即使按照C++的方式来使用,即#include 这种形式,那么符号可以位于命名空间std中,也可以位于全局范围中:

【C++】命名空间_第4张图片

如果我们将C++的cstdio头文件换成C语言的stdio.h头文件:

【C++】命名空间_第5张图片

原因是cstdio里的内容都被包含在std命名空间中,而stdio.h里的内容暴露在全局里!

C++将C语言的头文件形式全部由.h结尾改成了以c开头,可能是为了和自己的一套规范相匹配,比如标准C++之前iostream的写法是iostream.h。

不仅仅是头文件里定义的各种变量、函数等,我们自己定义的一系列东西如果暴露在全局里,就很容易造成命名冲突,因此我们在工作中使用C++语言进行工作时最好不要展开命名空间,那么接下来我们将继续介绍命名空间的使用以及作用域限定符。

4 命名空间的使用

namespace s3
{
	int a = 10;
	namespace s4
	{
		int a = 20;
	}
    int add(int x, int y)
	{
		return x + y;
	}
}

我拿嵌套命名空间的例子向大家介绍命名空间的使用:

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

#include
namespace s3
{
	int a = 10;
	namespace s4
	{
		int a = 20;
	}
    int add(int x, int y)
	{
		return x + y;
	}
}
int main()
{
    std::cout << "s3中的add(1,2)=" << s3::add(1,2) << std::endl;
	std::cout << "s3中的a=" << s3::a << std::endl;
	std::cout << "s4中的a=" << s3::s4::a << std::endl;
	return 0;
}

s4是包含在s3里的,所以要写成s3::s4

如果我们要进行大量的输入输出,一句一句写std::cout岂不是太麻烦了?

 4.2 使用using将命名空间中某个成员引入(最推荐)

为什么最推荐?

①减少代码量

②防止同名变量命名冲突

#include
using std::cout;
using std::endl;
namespace s3
{
	int a = 10;
	namespace s4
	{
		int a = 20;
	}
}
using s3::a;
using s3::s4;//err
using s3::add;
int main()
{
    cout << "s3中的add(1,2)=" << add(1,2) << endl;//3
	cout << "s3中的a=" << a << endl;//10
	cout << "s4中的a=" << s3::s4::a << endl;//20
	return 0;
}

注意,作用域限定符不支持后面跟命名空间:

【C++】命名空间_第6张图片

4.3 使用using namespace +命名空间名称

温馨提醒:平时我们自己写代码可以用,到公司上班了就最好不要写,和别人冲突了就不好了。

using namespace std;//放在头文件前后都可以
#include
//using namespace s3;//放在s3前面就err
namespace s3
{
	int a = 10;
	namespace s4
	{
		int a = 20;
	}
	int add(int x, int y)
	{
		return x + y;
	}
}
using namespace s3;//ok
int main()
{
	cout << "hello world" << endl;
	cout << "s3中的a=" << add(1,2) << endl;
	cout << "s3中的a=" << a << endl;
	cout << "s4中的a=" << s4::a << endl;
	return 0;
}

使用using namespace+命名空间名称,就相当于少写了一层作用域限定符。

需要注意的是,展开自己的命名空间和展开标准命名空间,自己的必须写在命名空间的定义下面std的既可以写在头文件上方也可以写在头文件下方

5 总结

  本文介绍了C++的命名空间,C++的命名空间是为了解决C语言命名冲突的缺陷提出的,对于命名空间的使用,我推荐大家用4.2中的用法,这样有利于培养起优质的代码习惯!

  另外,今天是10/24,祝各位程序员节快乐!

你可能感兴趣的:(1024程序员节,c++)