首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C++入门基础(一):C++的发展历史、C++的第一个程序 、命名空间、C++输⼊&输出、命名空间的使用等内容介绍

C++入门基础(一):C++的发展历史、C++的第一个程序 、命名空间、C++输⼊&输出、命名空间的使用等内容介绍

作者头像
用户11831438
发布2025-12-30 12:31:37
发布2025-12-30 12:31:37
370
举报
一、C++的发展历史

C++的起源可以追溯到1979年,当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普,这个翻译的名字不同的地方可能有差异)在贝尔实验室从事计算机科学和软件工程的研究工作。⾯对项目中复杂的软件开发任务,特别是模拟和操作系统的开发⼯作,他感受到了现有语⾔(如C语⾔)在表达能力、可维护性和可扩展性方面的不⾜。

1983年,Bjarne Stroustrup在C语⾔的基础上添加了面向对象编程的特性,设计出了C++语言的雏形,此时的C++已经有了类、封装、继承等核心概念,为后来的面向对象编程奠定了基础。这⼀年该语⾔被正式命名为C++。

在随后的⼏年中,C++在学术界和⼯业界的应⽤逐渐增多。⼀些⼤学和研究所开始将C++作为教学和研究的⾸选语言,而⼀些公司也开始在产品开发中尝试使⽤C++。这⼀时期,C++的标准库和模板等特性也得到了进⼀步的完善和发展。

C++的标准化⼯作于1989年开始,并成立了⼀个ANSI和ISO(International Standards Organization)国际标准化组织的联合标准化委员会。1994年标准化委员会提出了第⼀个标准化草案。在该草案中,委员会在保持斯特劳斯特卢普最初定义的所有特征的同时,还增加了部分新特征。

在完成C++标准化的第⼀个草案后不久,STL(Standard Template Library)是惠普实验室开发的⼀系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室⼯作时所开发出来的。在通过了标准化第⼀个草案之后,联合标准化委员会投票并通过了将STL包含到C++标准中的提议。STL对C++的扩展超出C++的最初定义范围。虽然在标准中增加STL是个很重要的决定,但也因此延缓了C++标准化的进程。

1997年11⽉14⽇,联合标准化委员会通过了该标准的最终草案。1998年,C++的ANSI/IS0标准被投入使用。

二、C++的第一个程序

C++兼容C语言绝⼤多数的语法,所以C语言实现的hello world依旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到是.cpp就会调用C++编译器编译,linux下要用g++编译,不再是gcc。

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

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

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

代码语言:javascript
复制
#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
复制
#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
复制
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
复制
#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
复制
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
复制
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
复制
//嵌套命名空间域的使用
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))的标准输入流。

cin是把这个字符串(因为我们从键盘上输入的都可以认为是字符串)转换成int,char等类型

  • std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流。

int i=10;std::cout<<i; 把i这个类型的对象转换成字符串插入到cout中,然后输出; std::cout<<i 的特点是自动识别类型,并且不同类型可以连续在一起; 任何变量都转换成字符串插入到流中(可以认为是控制台)

  • std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区
代码语言:javascript
复制
//换行
int main()
{
	int i = 0;
	std::cout << i << '\n';//-->不刷新缓冲区
	std::cout << i << "\n";
	std::cout << i << std::endl;//-->刷新缓冲区
	return 0;
}

建议在竞赛中使用上面两个换行,上面两个不刷新缓冲区

  • <<是流插入运算符,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移)

写到这里不知道会不会有小伙伴会有疑问?上面我们在写换行的代码时,每写一句都要写上std::cout,std::endl,以及std::cin,每当我使用cout和cin的时候都要加上std,感觉好麻烦,那这个std可不可以不写?接下来我们来看一下

五、 命名空间的使用

编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下⾯程序会编译报错。

代码语言:javascript
复制
namespace st
{
	int rand = 10;
	struct node
	{
		int* arr;
		int size;
		int capacity;
	};
	int Add(int left, int right)
	{
		return left + right;
	}
}
int main()
{
	printf("%d\n", rand);
	return 0;
}

当我们运行上面代码时,编译器会报错,如果不使用域操作符,编译器默认先从局部域中查找是否存在变量rand,如果没有,则在全局域中查找变量rand,如果都没有,则报错。

代码语言:javascript
复制
namespace st
{
	int rand = 10;
	struct node
	{
		int* arr;
		int size;
		int capacity;
	};
	int Add(int left, int right)
	{
		return left + right;
	}
}
int main()
{
	printf("%d\n", st::rand);
	return 0;
}

所以我们要使用命名空间中定义的变量/函数,有三种方式:

  • 指定命名空间访问,项目中推荐这种方式。
  • using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
代码语言:javascript
复制
#include<iostream>
using std::cout;//-->部分展开命名空间
using std::endl;
int main()
{
	int i = 10;
	cout << i << endl;
	return 0;
}

  • 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
代码语言:javascript
复制
using namespace std;//-->展开命名空间(全部展开)
int main()
{
	int i = 10;
	cout << i << endl;
	return 0;
}

总结:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、C++的发展历史
  • 二、C++的第一个程序
  • 三、命名空间
    • 3.1 namespace的价值
    • 3.2 namespace的定义
  • 四、 C++输入&输出
  • 五、 命名空间的使用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档