当前位置: 首页 > news >正文

C++入门(上) -- 讲解超详细

在前面我们已经学习了C语言和数据结构,这一节正式迈入C++阶段了。

关于C++,我们先来了解一下C++的发展历史。

1. C++发展历史

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

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

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

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

在完成C++标准化的第一个草案后不久,STL(StandardTemplateLibrary)是惠普实验室开发的⼀系列软件的统称。它是由AlexanderStepanov、MengLee和DavidRMusser在惠普实验室工作时所开发出来的。在通过了标准化第一个草案之后,联合标准化委员会投票并通过了将STL包含到C++标准中的 提议。STL对C++的扩展超出C++的最初定义范围。虽然在标准中增加STL是个很重要的决定,但也因 此延缓了C++标准化的进程。1997年11月14日,联合标准化委员会通过了该标准的最终草案。1998年,C++的ANSI/IS0标准被投入使用。

当然C++并不是一下就变成如今的样子,而是不断的发展更新,C++有许多版本,我们来看一看它每一个版本的改进。

2. C++版本更新

这里是博主在百度上面查询得到的,有兴趣的可以去搜索一番。

我们可以看到C++大概每3年就会进行一次版本的更新。

3. C++在工作领域中的应用

1. 大型系统软件开发。如编译器、数据库、操作系统、浏览器等等

2. 音视频处理。常见的音视频开源库和方案有FFmpeg、WebRTC、Mediasoup、ijkplayer,音视频开发最主要的技术栈就是C++。

3. PC客户端开发。一般是开发Windows上的桌面软件,比如WPS之类的,技术栈的话一般是C++和QT,QT是一个跨平台的C++图形用户界面(GraphicalUserInterface,GUI)程序。

4. 服务端开发。各种大型应用网络连接的高并发后台服务。这块Java也⽐较多,C++主要用于⼀些对性能要求比较高的地方。如:游戏服务、流媒体服务、量化高频交易服务等

5. 游戏引擎开发。很多游戏引擎就都是使用C++开发的,游戏开发要掌握C++基础和数据结构,学习图形学知识,掌握游戏引擎和框架,了解引擎实现,引擎源代码可以学习UE4、Cocos2d-x等开源引擎实现

6. 嵌入式开发。嵌入式把具有计算能力的主控板嵌入到机器装置或者电子装置的内部,通过软件能够 控制这些装置。比如:智能手环、摄像头、扫地机器⼈、智能音响、门禁系统、车载系统等等,粗略一点,嵌入式开发主要分为嵌入式应用和嵌入式驱动开发。

7. 机器学习引擎。机器学习底层的很多算法都是用C++实现的,上层用python封装起来。如果你只想准备数据训练模型,那么学会Python基本上就够了,如果你想做机器学习系统的开发,那么需要学 会C++。

8. 测试开发/测试。每个公司研发团队,有研发就有测试,测试主要分为测试开发和功能测试,测试开发一般是使用一些测试工具(selenium、Jmeter等),设计测试用例,然后写一些脚本进行自动化测试,性能测试等,有些还需要自行开发一些测试用具。功能测试主要是根据产品的功能,设计测试用例,然后手动的方式进行测试。

博主在boss上面找了一些相关的岗位信息,C++适用范围很广。

当然C++学习的难度也很大,不知道你们有没有看到过这样一幅图:

C++的学习之路很长,每天都在不断的学到新的知识,也是不断提升能力的一个过程,好了话不多说,我们正式进入C++的学习之旅!

4. C++的第一个程序

在C语言中,我们接触到的第一个程序是“hello,world”

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

在C++中兼容C语言的绝大多数语法,C语言的“hello,world”在C++中也能执行,C++定义文件时需要将文件后缀改为.cpp,这样编译器在看到.cpp后缀是会调用C++编译环境,同样Linux下要用g++编译,不再是gcc了。

那么在.cpp文件里,这个程序该怎么写呢?

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

这里会有同学问,这个iostream,std等等是个什么?不要担心,后面会讲解。

这就是C语言第一个程序转换为C++的写法。

5. 命名空间

5.1 namespace

在C语言中,我们的变量大多都是局部变量,全局变量,在C++中我们称之为局部域和全局域。

同时在C语言中,我们的变量名不能重复,不然会编译错误,这个时候C++提出了改进的方法,创建一个域(namespace),域的名称有我们自己定义,把冲突的变量放到域里面,就不会编译错误了。这就是命名空间域,其目的是为了解决命名冲突问题。

在C语言中,我们写了这样一个程序:

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

但是在.cpp文件中却编译错误

欸,你会发现rand即使全局变量,又是一个函数,出现了重命名冲突,如何解决它呢?

我们写一个命名空间域,把它放在域里面:

#include <iostream>
using namespace std;namespace A
{int rand = 10;
}int main()
{printf("%d ", rand);return 0;
}

这样编译不会报错,这里的rand,编译器认为是rand函数,那问题来了,为什么这里不会打印10?

这时因为命名空间的特性,命名空间域相当于一个独立的空间,相当于与世隔绝,你不能找到我,同样里面的值你也拿不到,下面我们就来讲解命名空间的定义

5.2 命名空间的定义

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

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

#include <iostream>
using namespace std;
//命名空间的定义
namespace xiaoli
{int rand = 10;int add(int x, int y){return x + y;}
}
int main()
{//这里默认访问的是全局rand函数指针printf("%p ", rand);//这里访问的是命名空间域里面的randprintf("%d ", xiaoli::rand);return 0;
}

3.C++域包含全局域,局部域,命名空间域,类域,域影响的是编译器查找变量/函数/类类型出处(声明或定义)的逻辑,所以有了域,就避免了命名冲突的问题。

注意:命名空间域只影响查找规则,而全局域和局部域不仅会影响查找规则还会印象生命周期。命名空间域和类域不影响变量生命周期。

4.命名空间只能定义在全局,可以嵌套定义。

//嵌套定义
namespace xiaoli
{int rand = 10;int add(int x, int y){return x + y;}namespace xiaowang{int age = 22;int heigh = 180;}
}

5.项目工程中多文件中同名namespace会认为是一个namespace,不会冲突。

(可以理解为分身,最后回归本身。)-- 这里就不演示了,可以下来自己尝试

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

5.3 命名空间的使用

命名空间是一个独立的空间,一般编译查找一个变量的声明/定义时,默认会在局部域和全局域里卖弄查找,不会到命名空间里面查找,这样容易导致编译报错。

如果要在命名空间里面查找,则可以通过以下几种办法:

1. 指定命名空间访问,项目中推荐这种方式。

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

3. 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。

#include <iostream>
using namespace std;namespace xiaoli
{int age = 30;int high = 180;int height = 120;namespace Add{int add(int x, int y){return x + y;}void swap(int x, int y){int tmp = x;x = y;y = tmp;}}}
// using将命名空间中某个成员展开
using namespace xiaoli::Add;
// 展开命名空间中全部成员
using namespace xiaoli;
int main()
{//// 指定命名空间访问(::是访问限定操作符,可以获取命名空间里的数据)//printf("%d ", xiaoli::age);//printf("%d ", xiaoli::height);//printf("%d ", xiaoli::high);//// using将命名空间中某个成员展开//int ret = add(5, 6);//printf("%d\n", ret);//// 展开命名空间中全部成员swap(5,6);return 0;
}

6. C++输入&输出

在前面我们提到了iostream 和 cout,这到底是什么呢?下面就来介绍

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

2. std::cin 是istream类的对象,主要面向窄字符的标准输入流。

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

(这里是什么意思呢?就是说cout和cin可以把任何类型转化为窄字符)

什么是窄字符?这里先不讲,后面到string的时候详细讲解,不然这里会很懵懂

4. std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。

5. << 是流插入运算符;>> 是流提取运算符

istream和ostream到底是什么?-- 这个后面再讲,现在先暂时理解为是一个库

<< 和 >> 通俗易懂的来说就是输入和输出,它可以自动识别类型并输入输出。相对于C语言的scanf 和 printf,无需输入数据的类型(本质是通过函数重载来实现,具体的还得到下面讲完函数重载),就可以达到我们想要的效果。

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

7. 一般日常练习中我们可以usingnamespacestd,实际项目开发中不建议using namespace std。一般部分展开或者指定域。

8. 在没有包含<stdio.h>时,也能使用scanf和printf,这时因为iostream间接包含了,在vs编译器是这样,其他编译器可能会报错。

7. 缺省参数

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

举个例子:

如图所示,第一次调用add的时候,没有指定实参(没有传参),那么就使用默认的值;第二次调用add的时候,指定了实参,就使用指定的值。是不是好理解一点呢?

有同学问:全缺省和半缺省有什么区别?

全缺省:全部形参给缺省值;半缺省:是部分形参给缺省值。

C++规定半缺省参数必须从右往左依次连续缺省,不能跳跃缺省。同理:带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参

什么意思呢?    就是说在传参的时候从右往左依次不给传参,不能跳跃

 // 全缺省
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 = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}int main()
{Func1();//10 20 30Func1(1);//1 20 30Func1(1, 2);//1 2 30Func1(1, 2, 3);// 1 2 3//error//Func1(1, ,3);//Func2();必须传一个参数Func2(5);//5 10 20Func2(5, 6);//5 6 20Func2(5, 6, 7);//5 6 7return 0;
}

最重要的一点:函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。

//stack.h
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;void STInit(ST* ps, int n = 4);// Stack.cpp
#include"Stack.h"// 缺省参数不能声明和定义同时给
void STInit(ST* ps, int n = 1000)
{assert(ps && n > 0);
}//test.cpp
#include"Stack.h"
int main()
{ST st1;STInit(&st1);ST st2;STInit(&st2, 1000);return 0;
}

当声明和定义同时给定参数时,我到底使用哪一个呢?这个优先顺序吗?-- 没有,所以编译器不知道使用哪一个值,便会报错。(就相当于,两个人同时抢到了优惠券,但是只有一个能使用,到底给谁用呢?一个道理)

8. 函数重载

在C语言中,同名变量和函数会报错,但是两个同名函数实现的功能又不是一样的,该怎么解决呢?C++为了解决这个问题引入了函数重载。

所以函数重载就是相同的名字,但实现功能不同,是不是这样呢?来看定义

定义:C++支持在同⼀作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同

举个例子:

// 参数类型不同
int add(int x, int y)
{cout << "int add(int x, int y)" << endl;return x + y;
}
int add(double x, int y)
{cout << "int add(double x, int y)" << endl;return x + y;
}// 参数个数不同
double add(int x, int y, int z)
{cout << "double add(int x, int y, int z)" << endl;return x + y;
}
double add(int x)
{cout << "double add(int x)" << endl;return x;
}// 参数顺序不同
void fun(float a,int b)
{cout << "int fun(int a,int b)" << endl;
}
void fun1(float b, int a)
{cout << "int fun1(float b, int a)" << endl;
}

注意:返回值不同不能看作函数重载!!!

// 参数类型不同
int add(double x, int y)
{cout << "int add(int x, int y)" << endl;return x + y;
}
double add(double x, int y)
{cout << "int add(double x, int y)" << endl;return x + y;
}

那么这一次就先到这里,下一次再用小部分篇幅结束C++入门余下内容。

http://www.dtcms.com/a/322075.html

相关文章:

  • 【狂神说java学习笔记】四:java流程控制(用户交互Scanner、顺序结构、if选择结构、switch选择结构)
  • isulad + harbor私有仓库登录
  • 大模型性能测试实战指南:从原理到落地的全链路解析
  • Claude使用报错 Error: Cannot find module ‘./yoga.wasm‘
  • 鸿蒙中使用tree
  • 系统集成项目管理工程师【第十一章 规划过程组】规划成本管理、成本估算、制定预算和规划质量管理篇
  • 安全基础DAY1-安全概述
  • Xiphos Q8 摄像头板 高性能图像处理板
  • 案例实战:机器学习预测粘度+耐热高分子筛选,聚合物研发效率倍增秘籍
  • 锯床自动长度检测与参数闭环补偿系统
  • 2025年环境工程与新能源科学国际会议(EENES 2025)
  • x265开源编码器源码框架深度解析
  • 知识图谱【2】
  • 五、SpringBoot工程打包与运行
  • SpringAI实现多用户记忆隔离
  • 【SpringAI】9.创建本地mcp服务(演示通过mcp实现联网搜索)
  • Git Commit 命令详解:版本控制的核心操作
  • $QAXHoneypot是什么文件夹
  • 2025 蓝桥杯C/C++国B 部分题解
  • DAY34打卡
  • GDB 调试全方位指南:从入门到精通
  • try-catch-finally
  • 3-防火墙
  • 【JAVA EE初阶】多线程(进阶)
  • linux 一次性查看所有docker容器网络模式和端口映射
  • 打破枷锁:Python GIL下的并发突围之路
  • 两个函数 quantize() 和 dequantize() 可用于对不同的位数进行量化实验
  • 睿抗开发者大赛国赛-24
  • 【深度学习】动手深度学习PyTorch版——安装书本附带的环境和代码(Windows11)
  • 【实证分析】地区市场公平竞争程度数据集-含do代码(2012-2024年)