C++入门
目录
快速简介
01.基础语法
1.1 C++简单介绍
- 1.1.1 C++简介:
- 1.1.2 C++四大特性:
- 1.1.3 C++标准库:
- 1.1.4 C++编译器:
- 1.1.5 helloWorld:
- 1.1.6 多种注释:
- 1.1.7 命名空间:引入命名空间主要是作为附加信息来区分不同库中相同名称的函数、类、变量等。使用
using namespace 名称
可以通过该方式引入命名空间。 - 1.1.8 头文件名:
- 1.1.9 cout输出:
1.6 结构体复合类型
- 1.6.1 基本概念和定义
- 1.6.2 结构体数组
- 1.6.3 结构体指针
- 1.6.4 结构体嵌套结构体
- 1.6.5 结构体做函数参数
- 1.6.6 结构体const场景
- 1.6.7 结构体案例
02.运算符和表达式
03.判断和循环
04.函数实践
05.指针和引用
06.数组和容器
07.类和对象
7.1 面向对象思想
7.1.1 类的含义。类是面向对象编程基础,类是一种复杂数据类型的声明!
7.1.2 struct和class区别。class类默认成员属性是私有的,struct结构体默认成员属性是公开的。
7.2 类定义和对象
7.2.1 类的定义。用户自定义类型,设计类将属性和行为写到一起表现事物。可以把类看作模版。
7.2.2 创建对象。两种创建对象方式:待完善
7.2.3 访问类成员。创建对象以后,可以使用点号.来访问成员变量和成员函数!
7.2.4 对象指针。
7.2.5 案例实践
7.3 类成员属性
7.3.1 成员变量
7.3.2 成员函数
7.3.3 访问权限
7.3.4 成员设置私有
7.3.5 案例实践
7.4 对象初始化
7.4.1 构造和析构函数。构造函数在初始化对象时用到;析构函数对象销毁前调用。这两个编译器默认的是空实现!
7.4.2 构造函数分类。分为有参数构造和无参数构造。调用构造函数有三种方式:括号法,显示法,隐式转换法。
7.4.3 拷贝构造函数。三种方式:1.使用一个创建完毕对象来初始化新对象,2.给函数参数传递;3.值方式返回局部对象。
7.4.4 构造调用规则。默认构造函数,如果用户定义构造则不会创建默认构造函数。
7.4.5 初始化列表。
7.5 类对象使用
7.5.1 类对象作为类成员
类中的成员可以是另一个类的对象。举一个例子,手机是一个A类,学生是一个B类,每个学生会有一个手机。把A类可以看作是:对象成员!
那么当创建B对象时,A与B的构造和析构的顺序是谁先谁后?构造函数顺序是:先调用对象成员的构造,再调用本类构造;析构函数顺序跟构造顺序刚好相反。
7.6 对象模型和this指针
7.6.1 变量和函数存储
在C++中,类内的成员变量和成员函数分开存储。注意只有非静态成员变量才属于类的对象上。也可以理解为,静态变量,静态方法,普通方法都是不占用对象空间的。
7.6.3 空指针访问成员函数
C++空指针是可以访问成员函数,但是注意点:如果成员函数中用到了this指针则不可以
7.6.4 const修饰成员函数
成员函数后加const后我们称为这个函数为常函数。1.在常函数中不可修改成员属性,2.成员属性声明时加关键字mutable后,在常函数中依然可以修改。
7.7 友元函数和友元类
友元:目的就是让一个函数或者类,可以访问另一个类中私有成员。
三种实现:1.全局函数做友元;2.类做友元;3.局部函数做友元。
08.继承和派生
8.1 继承基础使用
- 8.1.1 继承基本语法:继承,针对有上下级关系的类,继承可以将子类少写很多重复代码【将通用代码抽取到父类】。
- 8.1.2 继承方式和访问性:语法:
class 子类 : 继承方式 父类
,继承后可访问性是指子类对父类成员访问权限(public,protected,private)。 - 8.1.3 继承中对象模型:
- 8.1.4 继承中构造和析构顺序:继承中,先调用父类构造函数,然后依次调用子类构造函数。注意,析构函数刚好相反。
- 8.1.5 继承同名成员处理方式:访问子类同名成员,直接访问即可。访问父类同名成员,则需要添加作用域。
- 8.1.6 继承同名静态成员处理:同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象 和 通过类名)
8.2 多重继承
- 8.2.1 多重继承定义:多重继承定义,多继承即一个子类可以有多个父类,它继承了多个父类的特性。C++允许一个类继承多个类。
- 8.2.2 多重继承二义性:多重继承,派生类从多个基类中继承相同成员函数或变量,可能会导致二义性问题,即编译器不知道使用那个基类成员,导致编译错误。解决办法是指定访问作用域!
- 8.2.3 多重继承的构造顺序:多重继承的构造函数的调用顺序是按照派生类中基类的声明顺序来确定的。析构函数调用顺序是先子类,后父类。
8.3 其他继承
- 8.3.1 菱形继承:类 A 派生出类 B 和类 C,类 D 继承自类 B 和类 C,这种叫做菱形继承。目前存在子类继承两份相同的数据,以及数据二义性问题。
- 8.3.2 虚继承:派生类对共同基类的继承是虚拟的,只会保留一个共同基类的实例,从而避免了多个拷贝和二义性。
09.多态与虚函数
9.1 多态概念
- 9.1.1 多态基本概念:满足条件是继承关系和子类重写父类中的虚函数。是指同一名字的事物可以完成不同的功能。比如动物抽象吃饭,小猫吃鱼,小狗吃屎!
- 9.1.2 多态分类:分类静态多态和动态多态。
- 9.1.3 多态案例一-计算器类:通过普通写法和多态技术实现需求,发现多态代码组织强,便于维护,可读性强。
9.2 多态和虚函数
- 9.2.1 虚函数和抽象类:使用virtual关键字来标识虚函数,在派生类中重写基类的虚函数。如果一个类中有虚函数,则这个类必定是抽象类!
- 9.2.2 虚函数VS纯虚函数:虚函数可以被派生类重写(覆盖);纯虚函数只是一种函数声明,具体要派生类实现,主要是定义抽象类。
- 9.2.3 虚函数注意事项:
- 9.2.4 多态案例二——制作饮品:用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶
- 9.2.5 虚析构和纯虚析构:使用多态,如果子类有属性开辟到堆区(new出来的),那父类指针在释放时无法调用子类析构代码,解决办法将父类析构函数改成虚析构或者纯虚析构
- 9.2.6 多态案例三-组装电脑:
- 9.2.7 虚函数实现动态绑定:
9.3 函数重载
- 9.3.1 什么叫函数重载:在同一个作用域,声明多个同名函数,但这些同名函数形式参数必须不同,这个叫函数重载。
10.多线程和并发
11.线程安全锁
12.内存分配堆和栈
12.1 内存分区模型
- 12.1.1 什么是动态内存
- 12.1.2 内存4个区域
- 12.1.3 代码区
- 12.1.4 全局区
- 12.1.5 栈(Stack)区
- 12.1.6 堆(Heap)区
12.9 数据拷贝
- 12.9.1 浅拷贝。指简单的赋值拷贝操作。
- 12.9.2 深拷贝。在堆区申请内存空间,然后进行拷贝操作。
13.IO流与文件
13.1 输入输出流
- 13.1.1 输入输出流:流是字节序列。如果字节流是从设备流向内存,这叫做输入操作。如果字节流是从内存流向设备,这叫做输出操作。
- 13.1.2 I/O库头文件:
<iostream>
分别对应于标准输入流、标准输出流。<iomanip>
声明对执行标准化 I/O 有用的服务。<fstream>
为用户控制的文件处理声明服务。 - 13.1.3 标准输出流cout:用cout可以向控制台输出打印值。它是
<iostream>
库中一部分,只需要使用<<
运算符即可。 - 13.1.4 标准输入流cin:用cin可以通过控制台输入值。它是
<iostream>
库中一部分,cin是与流提取运算符>>
结合使用的。 - 13.1.5 标准错误流cerr:预定义的对象 cerr 是 iostream 类的一个实例。cerr 对象附属到标准输出设备,通常也是显示屏。
- 13.1.6 标准日志流clog:预定义的对象 clog 是 iostream 类的一个实例。clog 对象附属到标准输出设备,通常也是显示屏。
13.2 文件操作实践
- 13.2.1 文件是什么:文件是长久保存在本地的,文件格式是指约定内容的含义,比如txt文本文件是约定成可见字符ASCII码。
- 13.2.2 文件类型分类:文本文件是以ASCII码存储在计算机中;二进制文件一般不能直接读懂需要编码。
- 13.2.3 操作文件类:ifstream:专用于从文件中读取数据;ofstream:专用于向文件中写入数据;fstream:既可用于从文件中读取数据,又可用于向文件中写入数据。
- 13.2.4 文本文件写:仅对文件写操作,使用ofstream,先打开文件,然后调用
ofs <<
写入数据。备注文件打开有多种方式,熟悉即可。 - 13.2.5 文本文件读:仅对文件读操作,使用ifstream,先打开文件,有4种方式可以读入数据。最后要关闭流对象。
- 13.2.6 二进制文件写:写文件主要利用流对象调用成员函数write。函数原型 :
ostream& write(const char * buffer,int len);
- 13.2.7 二进制文件读:读文件主要利用流对象调用成员函数read。函数原型:
istream& read(char *buffer,int len);
13.3 文件读写指针
- 13.3.1 文件错误与状态:文件错误和状态可以通过文件流对象的状态标志来表示。std::fstream类中定义了一些成员函数和状态标志,用于检测和处理文件错误和状态。
- 13.3.2 文件的追加:可以使用文件流对象的std::ofstream类来实现文件的追加操作。要实现文件的追加,需要在打开文件时指定追加模式。
- 13.3.3 文件结尾的判断:可以使用文件流对象的eof()函数来判断文件是否已经到达结尾。
- 13.3.4 在指定位置读/写文件:利用fstream读写操作,可以使用文件流对象的seekg()和seekp()函数来在指定位置进行文件的读取和写入操作。
14.异常处理
14.1 异常入门介绍
- 14.1.1 异常概念解释:程序错误主要分为,语法错误,逻辑错误和运行时错误。其中运行时错误,会导致程序异常且终止运行。
- 14.1.2 运行时异常案例:所谓抛出异常,就是报告运行时错误。如果没有处理错误,则系统会终止程序执行。
- 14.1.3 捕获异常:可以通过try和catch捕获异常。try用来检测异常,catch用来抓获异常。
- 14.1.4 发生异常位置:异常可以发生在当前的 try 块中,也可以发生在 try 块所调用的某个函数中,或者是所调用的函数又调用了另外的一个函数,异常都可以被try检测到。
14.2 多级catch匹配
- 14.2.1 多级catch使用:异常发生后程序会按照从上到下的顺序,将异常类型和 catch 所能接收的类型逐个匹配。匹配到 catch 就停止检索,没有找到匹配的 catch,交给系统处理,终止程序运行。
- 14.2.2 匹配中类型转换:
14.3 throw抛出异常
- 14.3.1 异常抛出概念:异常必须显式地抛出,才能被检测和捕获到;如果没有显式的抛出,即使有异常也检测不到。
- 14.3.2 throw抛异常用法:使用throw关键字后跟一个表达式,将异常抛出。这个表达式可以是任何类型,通常是一个异常类的对象。
- 14.3.3 throw异常规范:
14.4 exception异常
- 14.4.1 抛出标准异常:C++语言本身或者标准库抛出的异常都是 exception 的子类,称为标准异常(Standard Exception),直接写
catch(exception &e)
- 14.4.2 exception类介绍:
- 14.4.3 exception派生类:
- 14.4.4 定义新的异常:需要继承自std::exception或其派生类,通过自定义异常,可以更好处理特定的错误或者异常情况。
15.STL标准模板库
15.1 函数模版基础
- 15.1.1 模板的概念:主要是为了提高代码复用性。比如生活场景中,你可以用ppt模版快速创建内容
- 15.1.2 函数模板语法:建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。语法是:
template<typename T>
- 15.1.3 函数模板注意事项:1.自动类型推导场景,必须是类型一致才可以使用。2.模版必须确定出T类型才可以正常使用。
- 15.1.4 函数模板案例:
- 15.1.5 普通函数VS函数模板:普通函数调用可以发生自动类型转化,函数模版调用时自动类型推导场景不会类型转化,指定类型才可以发生类型转化。
- 15.1.6 普通函数与函数模板调用规则:1.如果两者都可实现则优先调普通函数;2.通过空模版参数列表强制调用函数模版;3.模版可以重载;
- 15.1.7 模板的局限性:模版通用性并非万能。有时候可以具体化模版类型来处理特殊类型。
15.2 类模板基础
- 15.2.1 类模板语法:类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板。语法是
template<typename T>
- 15.2.2 类模板与函数模板区别:类模版没有自动类型推导必须指定类型,类模版模版参数中可以有默认参数类型。
- 15.2.3 类模板中成员函数创建时机:类模版的成员函数并不是一开始就创造,在调用时才去创造的。
- 15.2.4 类模板对象做函数参数:是指类模版实例化出的对象,向函数传参的方式。有3种方式——>指定传入类型;参数模版化;整个类模版化
- 15.2.5 类模板与继承:
- 15.2.6 类模板成员函数类外实现:
- 15.2.7 类模板分文件编写:
- 15.2.8 类模板与友元:
- 15.2.9 类模板案例:通过自定义栈案例,操作int类型,string类型做插入和取出逻辑操作。学习类模版案例的强大