> 文章列表 > 在C上++!(上)

在C上++!(上)

在C上++!(上)

目录

一、传说中的C++:

二、C++发展史

三、应用领域

四、C++怎么学?

五、命名空间namespace

1、命名空间的作用

2、如何定义命名空间

3、嵌套定义命名空间及其访问

 ​编辑 4、命名空间的合并

六、简单输入输出

七、缺省参数

 1、全缺省参数

2、半/部分缺省参数

3、注意点


一、传说中的C++:

1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一
种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:C++是基于C语言而
产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的
程序设计,还可以进行面向对象的程序设计。

简单来说:C++就是在C语言的基础上进行扩充,有了类的概念,既包含了C语言面向过程的特点,还引入了面向对象的特点。它弥补了C语言的一些缺点/不足。

认识一下C++祖师爷,本贾尼。

二、C++发展史

C with
classes
类及派生类、公有和私有成员、类的构造和析构、友元、内联函数、赋值运算符
重载等
C++1.0 添加虚函数概念,函数和运算符重载,引用、常量等
C++2.0 更加完善支持面向对象,新增保护成员、多重继承、对象的初始化、抽象类、静
态成员以及const成员函数
C++3.0 进一步完善,引入模板,解决多重继承产生的二义性问题和相应构造和析构的处
C++98 C++标准第一个版本,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美
国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库)
C++03 C++标准第二个版本,语言特性无大改变,主要:修订错误、减少多异性
C++05 C++标准委员会发布了一份计数报告(Technical Report,TR1),正式更名
C++0x,即:计划在本世纪第一个10年的某个时间发布
C++11 增加了许多特性,使得C++更像一种新语言,比如:正则表达式、基于范围for循
环、auto关键字、新容器、列表初始化、标准线程库等
C++14 对C++11的扩展,主要是修复C++11中漏洞以及改进,比如:泛型的lambda表
达式,auto的返回值类型推导,二进制字面常量等
C++17 在C++11上做了一些小幅改进,增加了19个新特性,比如:static_assert()的文
本信息可选,Fold表达式用于可变的模板,if和switch语句中的初始化器等
C++20 自C++11以来最大的发行版,引入了许多新的特性,比如:模块(Modules)、协
程(Coroutines)、范围(Ranges)、概念(Constraints)等重大特性,还有对已有
特性的更新:比如Lambda支持模板、范围for支持初始化等

        自C++11发布以来,约定每3年发布一个版本。C++是在实践中发展自身的,正如马克思主义一样,实践是C++活的灵魂。C++20中更新了许多新特性,它建了一栋漂亮的高楼,但是由于时间的原因,装修还未完成。不知道2023年的C++23又会更新出什么新特性呢?

三、应用领域

从语言本身上来说,三十多年来,C++一直在所有语言排行榜中稳居前5。它在以下几个领域有着重要应用。

1. 操作系统以及大型系统软件开发
所有操作系统几乎都是C/C++写的,许多大型软件背后几乎都是C++写的,比如:
Photoshop、Office、JVM(Java虚拟机)等,究其原因还是性能高,可以直接操控硬件。

2. 服务器端开发
后台开发:主要侧重于业务逻辑的处理,即对于前端请求后端给出对应的响应,现在主流采
用java,但内卷化比较严重,大厂可能会有C++后台开发,主要做一些基础组件,中间件、
缓存、分布式存储等。服务器端开发比后台开发更广泛,包含后台开发,一般对实时性要求
比较高的(延迟低),比如游戏服务器、流媒体服务器、网络通讯等都采用C++开发的。

3. 游戏开发
PC平台几乎所有的游戏都是C++写的,比如:魔兽世界、传奇、CS、跑跑卡丁车等,市面上
相当多的游戏引擎都是基于C++开发的,比如:Cocos2d、虚幻4、DirectX等。三维游戏领
域计算量非常庞大,底层的数学全都是矩阵变换,想要画面精美、内容丰富、游戏实时性
搞,这些高难度需求无疑只能选C++语言。比较知名厂商:腾讯、网易、完美世界、巨人网
络等。

4. 嵌入式和物联网领域
嵌入式:就是把具有计算能力的主控板嵌入到机器装置或者电子装置的内部,能够控制这些
装置。比如:智能手环、摄像头、扫地机器人、智能音响等。
谈到嵌入式开发,大家最能想到的就是单片机开发(即在8位、16位或者32位单片机产品或者
裸机上进行的开发),嵌入式开发除了单片机开发以外,还包含在soc片上、系统层面、驱动
层面以及应用、中间件层面的开发。
常见的岗位有:嵌入式开发工程师、驱动开发工程师、系统开发工程师、Linux开发工程
师、固件开发工程师等。
知名的一些厂商,比如:以华为、vivo、oppo、小米为代表的手机厂;以紫光展锐、乐鑫为
代表的芯片厂;以大疆、海康威视、大华、CVTE等具有自己终端业务厂商;以及海尔、海
信、格力等传统家电行业。
随着5G的普及,物联网(即万物互联)也成为了一种新兴势力,比如:阿里lot、腾讯lot、京
东、百度、美团等都有硬件相关的事业部。

在分布式应用,数字图像处理等方面也有重要应用。

四、C++怎么学?

 如果仅从语言学习的角度上来说1,C++无疑是难度最高的一种之一。

 热爱,坚持,探索,沉淀,自我价值! 

五、命名空间namespace

1、命名空间的作用

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

简单来说:namespace起到了一个“隔离”的作用,是用来避免命名冲突或名字污染的。

1、与库冲突:在包含头文件时,往往会同时拷贝一些全局的符号、函数、类。此时如果在全局作用域中创建了同名的类型,就会产生命名冲突。

也是是说,编译器在我们后续访问时,会分不清我们到底使用的是库中的还是自己定义的。

  这里我们包含了stdlib.h,其中包含rand函数,若我们再在全局域中创建变量rand,就会产生命名冲突,为rand重定义。

2、与其他人冲突:当我们试图完成一个大型工程、项目时,不同的人可能会在全局作用域中创建同名的类型,也会导致同样的命名冲突。

例如:两个不同.c文件中,同时定义了全局的int a,合并后就重定义了。

C语言中,无法避免这样的缺陷,而在C++中,我们可以用namespace创建一个独立的域,独立于其它局部域以及整个全局域。

2、如何定义命名空间

 与结构定义有点像,namespace + 域名,{}内包含的是命名空间的成员(最后无分号)。

命名空间中可以定义变量/函数/类型。

namespace mine
{
// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}

例如:我可以定义一个变量rand,一个函数ADD,一种结点struct Node。

这里我的域名为mine,也就是说,我将这3种类型隔离在了我的域mine中,与其它域互不冲突。

注:同一个域中,不能有同名的变量/函数/类型。

3、嵌套定义命名空间及其访问

这里我在namespace N1中嵌套定义了一个namespace N2,这个N2是在域N1中的,如果在N1再定义一个namespace N2也是可以的。

 命名空间的访问:可以用两个冒号  ::  做到指定域访问。(命名空间名称及作用域限定符)

这里我创建了4个int a,分别是1、全局的。 2、N1的  3、N1中的N2中的  4、N2中的。

分别对其访问和打印。

命名空间的访问顺序:在C语言中,我们知道局部域和全局域中都有int a变量时,局部变量优先访问。而对于命名空间域中的成员,C++默认不会主动访问。

也就是说,如果没有定义局部变量和全局变量,只有命名空间中的int a时,如果不指定域,直接打印a,编译器会显示  a  未定义。

此时我们就需要使用using namespace 和using关键字,前者是将整个namespace“全局化”,后者是将某个命名空间域中的某个成员“全局化”。

全局化后,使用方法与全局定义的变量相同,编译器会主动访问。当然,此时也会产生相应的命名冲突的问题。

 
 4、命名空间的合并

对于2个同名的命名空间,在编译时,编译器会将二者合成一个命名空间。

当然,它们的成员不能同名。如果同名,可以在其中一个里嵌套一个新的namespace。

总结:命名空间是为了解决命名冲突和名字污染而产生的,命名空间域的定义,使得我们可以精准的定义+访问任何一个同名变量,避免了工程中的一系列问题,弥补C的一定缺陷。

六、简单输入输出

std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中

 

若想使用std--标准库命名空间中的特定成员,需要先包含对应的头文件。

对于基本输入输出流  cin  cout要包含  #include<iostream> 输入输出流。

 要注意,cout是标准库命名空间中的成员,使用时要指明命名空间为std。

因为cout  cin  endl(换行)这些都是常用的指令,我们可以将他们展开。

using std::cout;
using std::cin;
using std::endl;

 这样,后面可以直接用cout、cin即可,不用写std::

同时,最好不要展开整个std命名空间,例如  using namespace std,全部展开后就会产生相应的命名冲突的问题,平时为方便把常用的展开即可。

cin  cout  为IO流,<<流插入操作符,>>流提取操作符,可以自动识别类型,但有时会产生一定误差。

七、缺省参数

在C语言中,函数定义时有几个参数,我们传参也必须传入几个参数。为保证准确性,这一点是十分严格的。但是在某些情况下,会显得不那么便利。

例如,在对顺序栈初始化时。 

如果想要取改变初始容量,就必须改变#define定义的值,有时该操作可能没有那么方便。

void STInit(struct Stack* pst, int DefaultCapacity = 4)
{int* tmp = (int*)malloc(sizeof(int) * DefaultCapacity);if (NULL == tmp){perror("malloc fail");return;}pst->capacity = DefaultCapacity;pst->top = -1;
}

 

可以在函数中加一个参数DefaultCapacity表示默认的容量大小,并赋值为4.

这样以来,虽然有2个参数,但第二个可以认为是缺省参数。

不传第二个参数时,capacity为4,也可以指定传参,此处我传了100,capacity对应也为100.

 1、全缺省参数

 abc3个参数均赋了值,即全部的参数都可以缺省。 

2、半/部分缺省参数

 只缺省b和c两个参数,a不缺省。即a的值必须给出,Func至少一个参数。

3、注意点

 

对于abc3个参数,缺省的参数要从右开始,即如果缺省,则c一定是其中之一。

因为传参时是从左向右传,优先认为是左边的参数,这种规则是为了防止产生歧义。 

 

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

VS中,如果定义和声明在不同的文件中,以声明中的数据为准。