初始C++

简介: 初始C++

一、C++发展历史

       C++是一种广泛使用的高级编程语言,它由丹麦计算机科学家比雅尼·斯特劳斯特卢普(Bjarne Stroustrup)于1979年在AT&T贝尔实验室开始设计开发,并在1983年正式命名。

       C++的发展历程大致如下:

       1. 起源(1979年-1983年):斯特劳斯特卢普开始着手“C with Classes”的研发工作,旨在为C语言添加面向对象的特性。这门新语言保留了C语言的高效性和可移植性,同时引入了类、简单继承、内联机制、函数默认参数以及强类型检查等特性。

       2. 早期发展(1983年-1985年):1983年,“C with Classes”语言正式更名为C++。这一时期加入了许多重要特性,如虚函数、函数重载、引用机制(符号为&)、const关键字以及双斜线的单行注释(从BCPL语言引入)。

       3. 第一个版本发布(1985年):斯特劳斯特卢普的C++参考手册《C++ Programming Language》出版,同年C++的商业版本问世。由于当时C++没有正式的语言规范,这本书成为了业界的重要参考。

        4. 版本更新(1989年):引入了多重继承、保护成员以及静态成员等语言特性。

        5. 标准化(1998年):C++标准委员会发布了C++语言的第一个国际标准—ISO/IEC 14882:1998,即C++98。标准模板库(STL)也被纳入该标准。

        6. 修订与改进(2003年):针对C++98版本中的问题进行修订,发布了C++03。

        7. 新特性引入(2011年):新的C++标准C++11面世,Boost库对该版本影响很大,一些新模块直接衍生于Boost中的相应模块。C++11引入了众多新特性,包括正则表达式、完备的随机数生成函数库、新的时间相关函数、原子操作支持、标准线程库、一种新的for语法(能够和某些语言中的foreach语句达到相同效果)、auto关键字、新的容器类、更好的union支持、数组初始化列表的支持以及变参模板的支持等。

        8. 持续发展(2014年、2017年等):2014年发布了C++14标准,对C++11进行了一些小的改进和修复;2017年发布了C++17标准,引入了变量模板、文件系统库、并行算法等新特性。之后C++标准仍在不断更新和发展,以适应新的编程需求和技术趋势。 C++通过不断吸收新特性和改进,逐渐成为一种功能强大、灵活且高效的编程语言,被广泛应用于系统软件、游戏开发、嵌入式系统、大型数据库和交易系统等众多领域。

二、C++在⼯作领域中的应⽤

       C++在以下工作领域中有广泛的应用:

       1. 游戏开发:C++因其高效的性能和对硬件的直接控制能力,常用于开发大型游戏的核心引擎和关键模块。

       2. 操作系统开发:如 Windows、Linux 等操作系统的部分关键组件是用 C++编写的。

       3. 嵌入式系统:在诸如智能家居设备、汽车电子系统、工业控制系统等嵌入式领域,C++能够高效地利用有限的资源。

       4. 金融交易系统:需要处理大量数据和高并发交易,对性能要求极高,C++能够满足这种需求。

       5. 科学计算和数值分析:用于编写高性能的数值计算库和模拟软件。

       6. 图形图像处理:在图像和视频处理软件、计算机辅助设计(CAD)等领域,C++能够实现复杂的算法和高效的图形渲染。

       7. 网络编程:开发高性能的网络服务器和网络应用程序。

       8. 数据库系统:数据库的底层引擎和优化部分常使用 C++。

       9. 虚拟现实和增强现实:构建实时渲染和交互的系统。

       总之,在对性能、效率和资源控制要求较高的工作领域,C++都有着重要的地位。

三、参考文档

       Reference - C++ Reference

       cppreference.com

       说明:第⼀个链接不是C++官⽅⽂档,标准也只更新到C++11,但是以头⽂件形式呈现,内容⽐较易看好懂。后者是C++官网文档,信息很全,更新到了最新的C++标准,但是 相⽐第⼀个不那么易看。所以,我们可以结合使用。

四、C++程序

       C++语言是如何产生的?是咱们的祖师爷对于C语言的不满时所为做也。因此,C++兼容C语言。我们开始学C语言,我们启蒙代码为:

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

       在C++编译器中这个代码也可以运行。但,这毕竟不是正经的C++代码。就好比:普通话是我们的官方语言,但我说你们当地方言你肯定可以听明白。这毕竟不是官方的,我们肯定要明白官方的如何书写,代码如下:

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

       这里的代码看不明白,很正常,就好比你开始学C语言看不懂代码一样,跟着我学习脚本你肯定能看明白,接下来开始我们的学习吧!

五、命名空间

       1.什么是命名空间

               在C语言我们学习函数的时候,我们学习过生命周期这个概念。那么,什么是生命周期呢?生命周期通常指的是一个对象或变量从创建到销毁所经历的时间段。那么,命名空间是什么?咱们可以这样理解:在这个空间的生命周期内,对这个空间内的全部标识符起一个名字,可对其进行引用,可类似与C语言中的结构体。可用于解决以下情况:

#include<stdio.h>
#include<stdlib.h>//此处不包此头文件代码可正常运行,那该如何解决此处情况呢?
 
int main()
{
  int rand = 10;
  printf("%d\n", rand);//此处编译不通过原因为:在不包头文件前为变量,包含后为函数。
  return 0;
}

       解决方法如下:

#include<stdio.h>
#include<stdlib.h>
 
namespace example
{
  // 命名空间中可以定义变量/函数/类型
  int rand = 10;
}//注意:此处无;号
int main()
{
  printf("%d\n",example::rand );
  return 0;
}

               我们可用命名空间来解决此类问题。

       2.命名空间定义

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

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

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

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

               项⽬⼯程中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。

               C++标准库都放在⼀个叫std(standard)的命名空间中。

       3.命名空间使⽤

               编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间⾥⾯去查找。所以 下⾯程序会编译报错。所以我们要使⽤命名空间中定义的变量/函数,有三种⽅式:

                指定命名空间访问,项⽬中推荐这种⽅式。

                using将命名空间中某个成员展开,项⽬中经常访问的不存在冲突的成员推荐这种⽅式。

               展开命名空间中全部成员,项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤。

               对于第二种方式类似于C语言中头文件,在C语言进行编译时,编译器会把头文件里的东西拷贝过来。

六、C++输⼊&输出

       可参考以下代码:

#include<iostream>
using namespace std;
 
int main()
{
  int a = 1;
  double b = 0.1;
  char c = 'a';
  std::cout << a << " " << b << " " << c << endl;//可多个输出
  cout << a << " " << b << " " << c << endl;//此处可省略std原因为:std为全展开
  std::cin >> a;
  cin >> b >> c;//可多个输入
  cout << a << " " << b << " " << c << endl;
  return 0;
}

       • <iostream>是 Input Output Stream 的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输 出对象。

       • std::cin 是 istream 类的对象,它主要⾯向窄字符(narrow characters (of type char))的标准输 ⼊流。

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

       • std::endl 是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。

       • >是流提取运算符。(C语⾔还⽤这两个运算符做位运算左移/右移)

       • 使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊ 输出可以⾃动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是 C++的流能更好的⽀持⾃定义类型对象的输⼊输出。

       • IO流涉及类和对象,运算符重载、继承等很多⾯向对象的知识,这些知识我们还没有讲解,所以这 ⾥我们只能简单认识⼀下C++ IO流的⽤法,后⾯我们会有专⻔的⼀个章节来细节IO流库。

       • cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要 通过命名空间的使⽤⽅式去⽤他们。

       • ⼀般⽇常练习中我们可以using namespace std,实际项⽬开发中不建议using namespace std。

七、缺省参数

       • 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实参 则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。(有些地⽅把 缺省参数也叫默认参数)

       • 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左 依次连续缺省,不能间隔跳跃给缺省值。

       • 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。

       • 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。

       缺省参数可这样理解:你传参数时,这个函数有参数,不会使用这个函数本身的参数,使用你传来的参数;但当你传空参时,便会用函数本身参数。简单来讲便是:有的话,不考虑你;没有的话,便考虑你。(是不是像某个群体,这里希望各位不要成为缺省参数(手动[doge]))。

       可结合以下代码理解:

#include<iostream>
 
using namespace std;
 
void Func(int a = 0)
{
  cout << a << endl;
}
 
int main()
{
  Func();   // 没有传参时,使⽤参数的默认值
  Func(10); // 传参时,使⽤指定的实参
  return 0;
}
#include<iostream>
 
using namespace std;
 
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
  cout << "a = " << a << endl;
  cout << "b = " << b << endl;
  cout << "c = " << c << endl << endl;
}
 
//半缺省
void Func2(int a, int b = 20, int c = 30)//此处缺省要连续,不可跳跃且要从右向左,不可从左向右
{
  cout << "a = " << a << endl;
  cout << "b = " << b << endl;
  cout << "c = " << c << endl << endl;
}
 
int main()
{
  Func1();
  Func1(1);//此处参数从左向右替换
  Func1(1, 2);
  Func1(1, 2, 3);
 
  //Func2(); 此处参数不可传空,原因a未定义
  Func2(100);
  Func2(100, 200);
  Func2(100, 200, 300);
  return 0;
}

八、函数重载

       在C语言中,以加法函数为例,要是传参类型不同,我们就要对其进行重写一个函数且要用不同的函数名,是不是过于麻烦?这里简单说一下面向对象的三大特点之一——多态的思想来解决。

       C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同 名函数的。

       参考以下代码:

#include<iostream>
 
using namespace std;
 
//1.参数类型不同型
int Add(int left, int right)
{
  cout << "int Add(int left , int right)" << endl;
 
  return left + right;
}
 
double Add(double left, double right)
{
  cout << "double Add(double left , double right)" << endl;
 
  return left + right;
}
 
//2.参数个数不同
void Func()
{
  cout << "Func()" << endl;
}
 
void Func(int a)
{
  cout << "Func(int a)" << endl;
}
 
//3. 参数顺序不同
void F(int a, char b)
{
  cout << "F(int a, char b)" << endl;
}
 
void F(char b, int a)
{
  cout << "F(char b , int a)" << endl;
}
 
//注:返回值不同不能作为重载条件,因为无法区分
//void f()
//{
//  ;
//}
 
//int f()
//{
//  return 0;
//}
 
 
//以下两个函数虽然构成重载,但会有歧异,编译器无法明白调谁,无法运行
void f()
{
  cout << "f()" << endl;
}
 
void f(int a = 10)
{
  cout << "f(int a)" << endl;
}
 
int main()
{
  Add(10, 20);
  Add(10.1, 20.2);
 
  Func();
  Func(10);
 
  F(10, 'a');
  F('a', 10);
 
  return 0;
}

最后:

       今天的学习到这里就结束了,希望各位读者下去后能多练,不要因为简单从而对自己要求降低。


相关文章
|
6月前
|
算法
HashMap的默认初始长度是多少?为什么?
HashMap的默认初始长度是多少?为什么?
110 0
|
6月前
|
人工智能 分布式计算 Java
【c++】初始c++
【c++】初始c++
【c++】初始c++
|
6月前
|
存储 缓存 算法
HashMap 默认加载因子非得是0.75
HashMap 默认加载因子非得是0.75
36 0
|
算法 Python
通过初始时间和流逝的分钟数计算终止时间
通过初始时间和流逝的分钟数计算终止时间
99 0
|
Kubernetes pouch 开发者
K8S 初识_ K8S 初始总结 | 学习笔记
快速学习 K8S 初识_ K8S 初始总结
114 1
K8S 初识_ K8S 初始总结 | 学习笔记
|
存储 Java
HasMap初始容量设置
HasMap初始容量设置
103 0
|
机器学习/深度学习 人工智能 算法
【算法 | 实验8】分配最小页数(数组划分和最大值最小化问题)
【算法 | 实验8】分配最小页数(数组划分和最大值最小化问题)
281 0
【算法 | 实验8】分配最小页数(数组划分和最大值最小化问题)
|
Oracle 安全 Java
JVM将初始和最大内存大小设置为相同值的好处
JVM将初始和最大内存大小设置为相同值的好处
1234 1
|
C#
【WindowsAPI之MoveWindow】 C#调整目标窗体的位置、大小
首先查看一下WindowsAPI给我们的解释  函数功能:该函数改变指定窗口的位置和尺寸。对于顶层窗口,位置和尺寸是相对于屏幕的左上角的:对于子窗口,位置和尺寸是相对于父窗口客户区的左上角坐标的。 函数原型:bool MoveWindow(HWND hWnd,int x,int y,int nWidth,int nHeight,bool BRePaint);   参数: hWnd:窗口句柄。
1962 0