在C语言的学习中,我们写过C语言的第一个程序:

代码语言:javascript

AI代码解释

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

当然C++有⼀套自己的输入输出,严格说C++版本的hello world应该是这样写的。

代码语言:javascript

AI代码解释

#include<iostream>
using namespace std;
int main()
{
	cout << "hello world!" << endl;
	return 0;
}

在上面的代码中,有很多新的东西,比如:iostream,namespace,std,cout,endl......这些究竟是什么?在接下来的学习中,我们都会学习到。

三、命名空间
3.1 namespace的价值

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

c语言项目类似下面程序这样的命名冲突是普遍存在的问题,C++引入namespace就是为了更好的解决这样的问题

代码语言:javascript

AI代码解释

#include<stdio.h>
#include<stdlib.h>
int rand = 10;
int main()
{
	printf("%d\n", rand);
	return 0;
}

当我们运行上面代码的时候,会出现下面的错误提示:

原因:在stdlib.h这个头文件中,rand是一个函数名,通过前面的学习,函数是作用于全局域的,而我们自己定义的变量rand也是一个全局变量,这就会出现名字冲突,为了解决这个问题,Bjarne博士发明了命名空间(namespace)了。

3.2 namespace的定义

1、定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。

代码语言:javascript

AI代码解释

namespace st//st为命名空间的名字
{
//命名空间中定义变量/函数/类型
	int a = 10;
	struct node
	{
		int* arr;
		int size;
		int capacity;
	};
	int Add(int left, int right)
	{
		return left + right;
	}
}

命名空间域的生命周期是整个函数,函数开始命名空间域开始,函数结束命名空间域结束,我们可以认为在命名空间中的是全局变量,提醒:不同域中可以定义同名的东西,但是相同域中不可以定义同名的东西,会发生冲突。

提醒:namespace 域名 { } 其中 { } 的括号后面没有“;”,这个要和定义结构体要有区别

2、namespace本质是定义出⼀个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。

代码示例:

代码语言:javascript

AI代码解释

#include<stdio.h>
#include<stdlib.h>
namespace st
{
	int rand = 10;
	struct node
	{
		int* arr;
		int size;
		int capacity;
	};
	int Add(int left, int right)
	{
		return left + right;
	}
}
int rand = 10;
int main()
{
	//这里默认是访问全局变量的函数指针rand
	printf("%p\n", rand);
	//这里访问的是namespace命名空间中的rand
	printf("%d\n", st::rand);
	return 0;
}

3、C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所以有了域隔离,名字冲突就解决了局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。

4、namespace只能定义在全局,当然他还可以嵌套定义。

代码语言:javascript

AI代码解释

namespace st
{
	namespace st1
	{
		int rand = 10;
		struct node
		{
			int* arr;
			int size;
			int capacity;
		};
		int Add(int left, int right)
		{
			return left + right;
		}
	}
	namespace st2
	{
		int rand = 10;
		struct node
		{
			int* arr;
			int size;
			int capacity;
		};
		int Add(int left, int right)
		{
			return left + right;
		}
	}
}

写到这里,就会有小伙伴提出疑问了?那既然有了命名空间。那我们该如何使用这个命名空间呢?

在学习如何使用这个命名空间之前,我们先学一个东西:

域操作符

:: 域操作符 如果::的左边没有任何东西,表示全局,如果有命名空间的名字,则表示该域中的东西

例如:

通过学习域操作符,接下来,让我们看看如何使用命名空间:

代码语言:javascript

AI代码解释

namespace st
{
	int rand = 10;
	struct node
	{
		int* arr;
		int size;
		int capacity;
	};
	int Add(int left, int right)
	{
		return left + right;
	}
}
int b = 20;
int main()
{
	int a = 10;
	// 编译器语法查找确认,默认规则先局部查找->全局查找->没有找到就报错未声明的标识符
	//默认是不会去命名空间的域中查找
	printf("%d\n", a);

	//::域操作符
	//如果::的左边没有任何东西,表示全局,如果有东西,则表示该域中的东西
	printf("%d\n", ::b);
	printf("%d\n", st::rand);
	printf("%d\n", st::Add(1, 2));
	//使用命名空间中的结构体需要像下面的写法
	struct st::node node1;
	return 0;
}

代码语言:javascript

AI代码解释

//嵌套命名空间域的使用
namespace st
{
	namespace st1
	{
		int rand = 10;
		struct node
		{
			int* arr;
			int size;
			int capacity;
		};
		int Add(int left, int right)
		{
			return left + right;
		}
	}
	namespace st2
	{
		int rand = 10;
		struct node
		{
			int* arr;
			int size;
			int capacity;
		};
		int Add(int left, int right)
		{
			return left + right;
		}
	}
}
int main()
{
	//调用st1中的加法函数
	st::st1::Add(2, 3);
	//调用st2中的加法函数
	st::st2::Add(3, 4);
	return 0;
}

注意:编译器语法查找确认,默认规则先局部查找->全局查找->没有找到就报错未声明的标识符,默认是不会去命名空间域中查找,除非使用域操作符,使用了域操作符,则直接去该域中查找->没有找到就报错未声明的标识符

5、项目工程中多文件中定义的同名namespace会认为是⼀个namespace,不会冲突。

这两个命名空间不会冲突,只会合并 6、C++标准库都放在⼀个叫std(standard)的命名空间中。

每当使用C++库时需要加上std


四、 C++输入&输出
  • <iostream> 是 Input Output Stream 的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
  • std::cin 是 istream 类的对象,它主要面向窄字符(narrow characters (of type char))的标准输入流。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐