c++的发展史、缺省参数、命名空间你了解吗?

1.c++的发展历史概述

1.1.什么是c++

C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的
程序,需要高度的抽象和建模时,C语言则不合适
。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
1982年Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一
种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计

1.2.c++的发展史

1979年,贝尔实验室的本贾尼等人试图分析unix内核的时候,试图将内核模块化,于是在C
语言的基础上进行扩展,增加了类的机制,完成了一个可以运行的预处理程序,称之为C with
classes。语言的发展就像是练功打怪升级一样,也是逐步递进,由浅入深的过程。我们先来看下C++的历史发展过程:

  1. 1979年:C语言的扩展:(本贾尼) Bjarne Stroustrup 在贝尔实验室工作时,开始着手开发一种能够支持面向对象编程的 C 语言扩展。这一过程中,他设计了 C++ 的最早版本。

  2. 1983年:正式命名为C++: Bjarne Stroustrup 在正式发布的 C++ 编程语言手册中首次使用了 "C++" 这个名称。这个名字表达了 C++ 是 C 语言的一个进化,并加上了一些面向对象编程的概念。

  3. 1985年:C++ 1.0 发布: 发布了 C++ 的第一个正式版本,包括类、继承、函数重载等基本的面向对象特性。

  4. 1989年:C++ 2.0 发布: 引入了多重继承、抽象类、静态成员函数等特性。

  5. 1990年:ANSI C++ 标准: 美国国家标准协会(ANSI)发布了第一个 C++ 标准,该标准在1998年被国际标准化组织(ISO)接受。

  6. 1998年:C++ 98 标准发布: ISO 发布了 C++ 的第一个国际标准,也称为 C++ 98。这个标准包括了许多新特性,如模板、命名空间、bool 类型等。

  7. 2003年:C++ 03 标准发布: 对 C++ 进行了一些小的修订,但主要是纠正和澄清了 C++ 98 中的一些问题。

  8. 2011年:C++ 11 标准发布: C++ 11 引入了许多新特性,包括自动类型推断、智能指针、lambda 表达式、范围循环等,使 C++ 编程更加现代化。

  9. 2014年:C++ 14 标准发布: 作为对 C++ 11 的小规模增强,引入了一些新特性,如二进制文字、泛型 Lambda 表达式等。

  10. 2017年:C++ 17 标准发布: 引入了一些新的语言特性和库特性,如结构化绑定、文件系统库、并发库等。

  11. 2020年:C++ 20 标准发布: C++ 20 是继 C++ 17 之后的新标准,引入了一系列新特性,如概念、范围语法、协程等。

1.3.c++的重要性

  1. 高性能: C++ 是一门编译型语言,直接翻译为机器代码,因此具有高性能。它允许对底层硬件进行更好的优化,使得 C++ 在系统编程、游戏开发等对性能要求较高的领域得到广泛应用。

  2. 面向对象编程: C++ 支持面向对象编程(OOP),使得代码能够更好地组织和管理。面向对象的特性,如封装、继承、多态等,使得代码更具可维护性和可扩展性。

  3. 跨平台性: C++ 的代码可移植性很强,可以在不同的操作系统和硬件平台上运行。这使得 C++ 成为开发跨平台应用和系统的重要选择。

  4. 系统级编程: C++ 被广泛用于系统级编程,如操作系统、驱动程序和嵌入式系统的开发。其直接的内存控制和硬件访问能力使其成为处理底层任务的理想语言。

  5. 游戏开发: 许多游戏引擎和游戏开发框架都是使用 C++ 编写的。C++ 提供了对图形和音频硬件的直接控制,以及对性能的高度优化,适合开发需要实时图形和音频处理的游戏应用。

  6. 大型软件项目: C++ 适用于大型软件项目的开发。其丰富的功能、模块化的设计和强大的标准模板库(STL)使得开发人员能够更容易地管理复杂的代码库。

  7. 嵌入式系统: C++ 被广泛用于嵌入式系统的开发,因为它提供了对硬件的底层访问、高效的代码执行以及对资源的有效管理。

  8. 科学计算和图形学: C++ 在科学计算和图形学领域得到广泛应用。它的性能和直接的硬件访问使其成为处理大规模计算和图形处理任务的理想选择。

补充

值得一提的是,c++兼容c语言,换句话来说,在.cpp文件中也可以写纯c语言的代码,这是没有问题的。但是如果想使用c++的一些库函数,就必须加入相应的头文件。

2.c++关键字

C语言32个关键字,而C++总计有63个关键字。

3.命名空间

命名空间(Namespace)是 C++ 中一种用于组织代码和防止命名冲突的机制。它允许开发者将代码元素(如变量、函数、类等)放置在一个特定的命名空间中,以避免与其他部分的代码发生冲突。通过使用命名空间,可以提高代码的可维护性和可读性。

观察以下代码:

#include <stdio.h>
#include <stdlib.h>
int a = 10;
int a = 10;
// 当我们定义两个同名变量的时候,如果这两个变量在同一域中,c语言就会报错
int main()
{printf("%d\n", a);return 0;
}

现实中,由于一个项目往往是由多个人一起完成的,如果两个人没有沟通好命名规则,那么很容易使用到同名的变量或者是同名的函数,这样对于多人合作完成一个项目来说是不利地。所以呢,c++就引入了命名空间这一概念。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的

使用命名空间就可以解决同名冲突问题: 

int a = 10;
namespace myname {int a = 10;
}
int main()
{printf("%d\n", myname::a);//命名空间的使用规则,在"::"右边声明空间域,表明该变量在哪里去找return 0;
}

3.1c/c++的变量搜索规则

一、对于c:

1、在局部域中搜索

2、局部域中没有就再去全局域中搜索

二、对于c++:

1、看变量左边有没有"::"。如果有,就去"::"左边的命名空间中去找,默认是全局域

例如 std::a,就是去名为std的空间里去找a。如果是::a,也就是"::"左边什么都不加,那就是去全局域中找a。

2、去局部域中搜索

3、去全局域中搜索

3.2命名空间定义

定义命名空间,需要使用到namespace关键字 ,后面加命名空间的名字,然后用一对{}括起来。{}中所有的变量或者函数都是该命名空间的成员。

namespace myname
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}//注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中struct Node{struct Node* next;int val;};
}

观察以下代码:

#include <stdio.h>
#include <stdlib.h>
#include<iostream>
namespace s1 {int A(int a, int b){return a + b;}
}
namespace s2 {int A(int a, int b) {return a * b;}
}
int main()
{printf("%d\n", s1::A(1 , 2));printf("%d\n", s2::A(2, 3));return 0;
}

我们可以看到,虽然s1和s2命名空间里面都有一个A(int,int)函数,但是各自实现的功能不一样,在s1命名空间里实现两数相加,在s2命名空间里面实现两数相乘。

 

3.3命名空间使用

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

1、加命名空间名称及作用域限定符
int main()
{
printf("%d\n", N::a);
return 0;
}
2、使用using将命名空间中某个成员引入

using s1::a的意思是将命名空间 s1 中的名称 a 引入到当前的作用域,使得在当前作用域中可以直接使用 a 而不需要通过命名空间限定符。

思考为什么输出a为10.

解释:

在这个例子中,using s1::a; 表示在 main 函数的作用域中引入了 s1 命名空间中的名称 a。因此,我们可以直接使用 a,而不需要写成 s1::a.又根据变量名的搜索原则,先在局部域搜索,发现局部域有a,那就不用在全局域中去搜索。这也是为什么输出的是10而不是1000.

3、使用using namespace 命名空间名称 引入
 跟第二点差不多,using namespace s1的意思是将命名空间 s1 中所有变量引入到当前的作用域。

思考:

以下代码为什么会报错

 

4.c++输入和输出

认识一门语言首先就要认识它的输入输出的方式。对于c++来说,它也有属于自己的输入输出方式。

#include<iostream>//c++标准输入输出库
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
cout<<"Hello world!!!"<<endl;
return 0;
}

说明:
1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件
以及按命名空间使用方法使用std
2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含<
iostream >头文件中。
3. <<是流插入运算符,>>是流提取运算符。
4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型

5.std命名空间

stdC++标准库中定义的一个命名空间。标准库是C++提供的一组通用的功能和工具,包括输入输出、容器、算法、字符串处理等。这些功能在 std 命名空间中组织,以便在用户的程序中使用。

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

 这也是为什么我们看到有的人用std::cout输出而不是cout

6.缺省参数

6.1缺省参数概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

举例

 6.2缺省参数分类

缺省参数分为半缺省参数和全缺省参数。半缺省参数就是函数中参数的缺省数目小于参数个数,也就是说,不是所有的参数都有缺省值,我们把这种不完全缺省的函数叫做半缺省。相对应地,所有参数都有缺省值就叫做全缺省参数

全缺省参数

void Func(int a = 1, int b = 1, int c = 1) {}//所有参数都设置缺省值,全缺省参数

半缺省参数

void Func(int a , int b=1 , int c=1) {}//不是所有参数都设置缺省值,半缺省参数

6.3注意

1.如果是半缺省参数,缺省值必须从右往左依次来给,不能间隔着给

2.缺省参数不能在函数声明和定义中同时出现

3.缺省值必须是常量或者是全局变量

4.c语言不支持(编译器不支持)

6.3.1为什么不能间隔着给呢?

原因是编译器需要能够准确地解析函数调用中各个参数的位置,而半缺省参数的提供是按照参数列表的最右端开始的。如果允许间隔着给参数赋值,编译器将难以判断参数的具体位置。为了避免这种歧义,C++ 编译器规定了半缺省参数必须按照声明的顺序提供。这样可以确保在函数调用时,参数的位置是明确的,编译器能够正确地解析。

举例

6.3.2 为什么缺省参数不能在定义和声明中同时出现?

避免二义性(Ambiguity): 如果函数的声明和定义中提供了不同的默认参数值,编译器无法确定在函数调用时应该选择哪个默认值。这会导致编译错误。

为了避免这些问题,C++ 编译器规定了默认参数只能在函数的声明或者定义中的其中一个地方提供。一般来说,建议在函数的声明中提供默认参数,而在函数的定义中不提供默认参数,这样可以使得函数的接口更清晰和一致。

6.3.3那么缺省参数应该在函数声明设置还是在函数定义设置呢?

观察以下代码

 以上代码将函数定义和函数声明分别放在a.cpp中和test.h中,main函数放在main.cpp文件中调用Func函数。我们发现,函数声明没有给缺省参数,函数定义给了,运行Func()函数却报错了。

报错信息

函数调用参数太少。可是按照我们设置缺省值的目的,虽然没有传参,但不应该使用的是默认值嘛?

也就是说,此时设置的缺省值并没有用。为什么?

原因在于,我们的函数声明放在了.h的头文件里,而在编译器的预编译阶段会将头文件的内容展开。test.h文件展开时只是展开了Func函数的声明,该声明设置了三个整型参数且没有缺省值。当系统在调用Func函数时,发现此时的Func函数需要三个整型参数并且没有缺省,所以就会立即报错并不会调用a.cpp文件里的Func函数。这里关于编译器预编译以及编译的几个阶段有不了解或者是想要了解的同学可以看我之前写的博客。

c语言的程序环境和预处理(一眼丁真)_c语言环境打击那-CSDN博客

 所以,缺省参数不能在函数声明和定义中同时出现,并且,应该在声明中设置缺省值而不是在定义中

虽然可以在main函数中定义Func函数,但是为了更好的维护代码一般我们不会这么做。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TypeScript实战系列之强力爆破泛型的困扰

目录 介绍开始如何理解泛型语法泛型约束泛型默认值练习后续 介绍 泛型在typescript 中使用频率相当高&#xff0c;也给了初学者相当大的阻碍。希望这一篇文章&#xff0c;能帮助你们爆破它。 开始 下面通过模拟实现一个简易版本的axios来引入泛型的使用 // axios.ts type M…

如何在centos7上配置为桥接模式

一、打开虚拟机的设置页面&#xff0c;设置虚拟机桥接模式如图&#xff1a;选择桥接模式&#xff08;复制物理网络连接可选&#xff09; 二、net0对应桥接模式的配置&#xff0c;如下方式选择 三、 在 CentOS 7 中&#xff0c;通过编辑网络配置文件来配置网络参数。找到 /etc…

(九)springboot实战——springboot3下的webflux项目参数验证及其全局参数验证异常处理

前言 在上一节内容中&#xff0c;我们介绍了如何在webflux项目中自定义实现一个全局的异常处理器ErrorWebExceptionHandler&#xff0c;正常情况下其可以处理我们系统的运行时异常&#xff0c;但是无法处理参数验证的异常WebExchangeBindException&#xff0c;所以这里提供另外…

算法随想录第四十八天打卡| 198.打家劫舍 , 213.打家劫舍II , 337.打家劫舍III

详细布置 今天就是打家劫舍的一天&#xff0c;这个系列不算难&#xff0c;大家可以一口气拿下。 198.打家劫舍 视频讲解&#xff1a;动态规划&#xff0c;偷不偷这个房间呢&#xff1f;| LeetCode&#xff1a;198.打家劫舍_哔哩哔哩_bilibili 代码随想录 class Solution(…

STM32 E18-D80NK红外避障传感器

E18-D80NK-N是一款红外光电传感器&#xff0c;它同时具备发射和接收功能。通过对发射光进行调制后发出&#xff0c;并通过接收头对反射光进行解调输出。 E18-D80NK-N采用了透镜来增强传感器的性能&#xff0c;使其能够检测更远的距离。根据红外光的特性&#xff0c;不同颜色的…

拒掉了一个双 985 的面试者

下班路上&#xff0c;和一个大佬聊天&#xff0c;他说今天面试&#xff0c;拒掉了一个双 985 的候选人。 候选人背景很好&#xff0c;本科和硕士都是 985 院校毕业&#xff0c;并且是除了清北浙之外&#xff0c;排名非常靠前的 985院校。 本硕专业都是计算机专业&#xff0c;…

Spring Boot + security + jwt 测试安全策略

一、测试概述 主要目的是测试security的用法。因测试搭建mysql和redis比较麻烦&#xff0c;所以我这里将自定义的jwt和用户信息缓存到程序的内存中。 本人测试的项目比较混乱&#xff0c;Spring Boot父类只标出有用的依赖。其子类用的版本为jdk11。后续会继续深入oauth2&#x…

数据库之TiDB基础讲解

文章目录 1 TiDB1.1 引言1.2 TiDB介绍1.3 系统架构1.3.1 TIDB Server1.3.2 PD Server1.3.3 TIKV Server1.3.4 TiKV如何不丢失数据1.3.5 分布式事务支持 1.4 与MySQL的对比1.5 性能测试1.5.1 测试一1.5.2 系统测试报告 2 1 TiDB 1.1 引言 当我们使用 Mysql 数据库到达一定量级…

调试小结:PHY初始化前后Link Status是否能正确反应网线插上、拔下状态

1 说明 为了验证是否需要初始化PHY才能检测到网线插上、拔下&#xff0c;这里我们对比初始化PHY&#xff08;LAN8720&#xff09;前后&#xff0c;插拔网线PHY寄存器1的bit2的是否按照预期变化来进行测试。 我们查看的PHY寄存器是1的bit2&#xff0c;定义如下&#xff1a; 2…

springboot的actuator

1、actuator简介 微服务的特点决定了功能模块的部署是分布式的&#xff0c;大部分功能模块都是运行在不同的机器上&#xff0c;彼此通过服务调用进行交互&#xff0c;前后台的业务流会经过很多个微服务的处理和传递&#xff0c;出现了异常如何快速定位是哪个环节出现了问题&am…

STM32 CAN接口中断处理与性能优化技巧

在基于STM32的CAN接口中&#xff0c;中断处理是一个非常重要的部分&#xff0c;它可以帮助我们实时地处理接收到的数据和处理其他CAN事件。为了优化CAN接口的性能&#xff0c;以下是一些中断处理和性能优化的技巧&#xff1a; ✅作者简介&#xff1a;热爱科研的嵌入式开发者&am…

系统架构19 - 面向对象

面向对象设计 相关概念面向对象分析基本步骤基本原则分析模型 面向对象设计设计模型类的类型 面向对象编程基本特点需求建模设计原则面向对象软件测试 相关概念 接口&#xff1a;描述对操作规范的说明&#xff0c;其只说明操作应该做什么&#xff0c;并没有定义操作如何做。消…

C与C++相互调用的“底层原理“

在你的C语言代码中&#xff0c;不知能否看到类似下面的代码&#xff1a; 这好像没有什么问题&#xff0c;你应该还会想&#xff1a;“嗯⋯是啊&#xff0c;我们的代码都是这样写的&#xff0c;从来没有因此碰到过什么麻烦啊&#xff5e;”。 你说的没错&#xff0c;如果你的头…

ES6理论及方法

一、基础知识 1.不可枚举就是不可遍历。 2.数据代理&#xff1a;通过一个对象代理对另一个对象中属性的操作&#xff08;读/写&#xff09; 二、方法 1.一个字符串是否包含在另一个字符串中 includes()&#xff1a;返回布尔值&#xff0c;表示是否找到了参数字符串。 starts…

Excel中将16进制数转化成10进制(有/无符号)

Excel中将16进制数转化成10进制&#xff08;有/无符号&#xff09; Excel或者matlab中常用XXX2XXX进行不同进制的转换 16进制转10进制&#xff08;无符号数&#xff09;&#xff1a;HEX2DEC 16进制转10进制&#xff08;有符号数&#xff09;&#xff1a; FA46为例&#xff0c…

看到小米SU7这顶配价格 全都坐不住了

文 | AUTO芯球 作者 | 李诞 果然被我猜中了吗&#xff1f; 我是真的猜中了吗 之前我的视频里说 小米SU7这技术、这车 绝对值35万 今天爆出来 小米汽车上牌售价 保险费用显示顶配36.14万 难怪雷总说 这是按照Dream Car的标准来设计的 投入百亿 雷总这点是真没骗人 …

架构整洁之道-价值维度与编程范式

1 设计与架构究竟是什么 结论&#xff1a;二者没有任何区别&#xff0c;一丁点区别都没有。 架构图里实际上包含了所有底层设计细节&#xff0c;这些细节信息共同支撑了顶层的架构设计&#xff0c;底层设计信息和顶层架构设计共同组成了整个架构文档。底层设计细节和高层架构信…

Matplotlib应用-股票技术分析实战

MACD Moving Average Convergence/Divergence&#xff0c;意为异同移动平均线。它刻画的是股价变化的速度 MACD算法 指标含义公式短期EMA短期收盘价指数移动均线(12天)前一日EMA(12)11/13 今日收盘价2/13长期EMA长期收盘价指数移动均线(26天)前一日EMA(26)25/27 今日收盘价2…

数据结构——并查集

1.并查集的定义 并查集其实也是一种树形结构&#xff0c;在使用中通常用森林的方式来表示 并查集的逻辑结构其实就是集合 并查集一般可以通过双亲写法&#xff08;顺序结构&#xff09;来完成&#xff0c;即通过一个数组存储父亲结点的下标 int s[10005]; int main() {for(…

深入了解Yum:Linux系统的软件包管理利器

目录 软件包 软件包的来源 关于yum yum是什么 yum的相关操作 介绍rzsz rz&#xff08;从Windows本地传到Linux服务器&#xff09; sz&#xff08;从Linux服务器传到Windows本地&#xff09; 注意事项 查看软件包 安装软件 卸载软件 yum的本地配置 为什么要进行配置…