C++-从入门到脊椎病康复
前言
C++ 是一种高级编程语言,由比约恩·斯特劳斯特鲁普于 1979 年开发。它是一种通用的、面向对象的语言,这意味着它可以用于构建各种应用程序,并且支持面向对象的编程范例。
C++ 的特点:
- 效率高:C++ 是编译型语言,这意味着它直接转换为机器代码,使其运行速度非常快。
- 面向对象:C++ 允许你将程序组织成对象,每个对象都包含数据和操作数据的方法。
- 通用:C++ 可以用于构建各种应用程序,从操作系统到图形界面再到嵌入式系统。
- 低级控制:C++ 提供对底层硬件和内存的低级访问,使其适合需要精细控制的应用程序。
- 静态类型检查:C++ 在编译时检查数据类型,这有助于防止运行时错误。
C++ 的应用:
C++ 被广泛用于开发以下类型的应用程序:
- 操作系统(如 Windows、Linux)
- 游戏引擎(如虚幻引擎、Unity)
- 数据库系统(如 MySQL、PostgreSQL)
- 嵌入式系统(如汽车控制、医疗设备)
- 金融软件(如交易平台)
变量类型
C++ 提供了多种变量类型,用于存储不同类型的数据。以下是 C++ 中所有变量类型的列表,示例:
- 整型
bool
: 布尔值(true 或 false)char
: 单个字符short
: 短整型(通常为 16 位)int
: 整型(通常为 32 位)long
: 长整型(通常为 64 位)long long
: 长长整型(通常为 128 位)
- 浮点型
float
: 单精度浮点数(通常为 32 位)double
: 双精度浮点数(通常为 64 位)long double
: 长双精度浮点数(通常为 80 位或 128 位)
- 其他类型
void
: 表示没有返回值的函数wchar_t
: 宽字符(通常为 16 位或 32 位)string
: 字符串(表示为字符数组)
示例
1 | // 整型 |
注意:
- 变量类型的选择取决于要存储的数据类型和所需的大小和精度。
- C++ 还提供了引用、指针和数组等其他数据类型,用于存储和操作复杂数据结构。
常量类型
C++ 提供了多种常量类型,用于存储不会改变的值。以下是 C++ 中所有常量类型的列表,示例:
- 整型常量
const bool
: 布尔常量(true 或 false)const char
: 字符常量const short
: 短整型常量const int
: 整型常量const long
: 长整型常量const long long
: 长长整型常量
- 浮点型常量
const float
: 单精度浮点数常量const double
: 双精度浮点数常量const long double
: 长双精度浮点数常量
- 其他类型常量
const void
: 表示没有返回值的函数常量const wchar_t
: 宽字符常量const string
: 字符串常量
示例
1 | // 整型常量 |
注意:
- 常量一旦声明就不能被修改。
- 常量类型的选择取决于要存储的数据类型和所需的大小和精度。
- C++ 还提供了枚举和宏等其他常量类型,用于存储和操作符号常量。
数据类型
- 数组:存储相同数据类型的多个元素
- 指针:存储其他变量的地址
- 结构体:存储不同数据类型的相关数据的集合
- 联合:存储不同数据类型的相同内存空间
- 枚举:存储一组常量
例:
1 | // 数组 |
其他数据类型
- 引用:别名,指向另一个变量
- 类型定义:创建新的数据类型
- 空类型:表示未知或无效的数据类型
例:
1 | // 引用 |
运算符
C++ 中的运算符用于执行各种操作,包括算术、逻辑和比较。
算术运算符:
+
加法-
减法*
乘法/
除法%
求余
逻辑运算符:
&&
与||
或!
非
比较运算符:
==
等于!=
不等于<
小于>
大于<=
小于或等于>=
大于或等于
例:
1 | int sum = a + b; // 算术运算符 |
控制流
控制流语句用于控制程序执行的顺序。
条件语句:
if-else
:根据条件执行不同的代码块switch-case
:根据给定值执行不同的代码块
循环语句:
for
:重复执行代码块一定次数while
:重复执行代码块,直到条件为假do-while
:先执行代码块,然后再检查条件
例:
1 | // if-else 语句 |
类、对象和继承
类
类是 C++ 中用户定义的数据类型,它封装了数据和操作数据的方法。类充当对象的蓝图,定义了对象的属性和行为。
对象
对象是类的实例,它包含类定义的数据和方法。对象是程序中实际存在的实体,可以与其他对象交互。
继承
继承允许一个类(称为派生类)从另一个类(称为基类)继承数据和方法。派生类可以访问和修改基类的数据和方法,并可以定义自己的新数据和方法。
类和对象的语法
1 | // 定义类 |
继承的语法
1 | // 定义基类 |
类的类型
- 公有类:成员对所有其他类和函数可见
- 保护类:成员对派生类可见,但对其他类和函数不可见
- 私有类:成员仅对类本身可见
继承类型
单继承:派生类从一个基类继承
多重继承:派生类从多个基类继承
多态:派生类对象可以以与基类对象相同的方式使用
多态、抽象类和接口
多态
多态(polymorphism)允许具有不同实现的类表现出相同的接口。换句话说,它允许派生类对象以与基类对象相同的方式使用。
抽象类
抽象类是不能被实例化的类。它们用于定义派生类必须实现的接口。抽象类中至少有一个纯虚函数(没有函数体的函数)。
接口
接口是仅包含纯虚函数的类。它们用于定义一组必须由实现它们的类实现的方法。接口不能被实例化,但可以作为基类用于多重继承。
多态、抽象类和接口的示例
1 | // 定义接口 |
在这个示例中,Shape
是一个接口,Rectangle
是一个抽象类,Square
是一个派生类。area()
方法在 Rectangle
和 Square
类中被重新实现,提供了不同的实现。通过使用多态,我们可以使用相同的接口调用不同类的 area()
方法。
容器、算法和 I/O 流
容器
容器是用于存储和组织数据的对象。C++ 标准库提供了各种容器,包括:
- 序列容器:存储元素的顺序集合,如
vector
、list
和deque
- 关联容器:存储键值对的集合,如
map
和set
- 无序关联容器:存储键值对的无序集合,如
unordered_map
和unordered_set
算法
算法是对容器或其他数据结构执行操作的函数。C++ 标准库提供了许多算法,包括:
- 搜索算法:查找元素或值,如
find
、binary_search
和lower_bound
- 排序算法:对元素进行排序,如
sort
、stable_sort
和partial_sort
- 修改算法:修改容器的内容,如
push_back
、erase
和replace
I/O 流
I/O 流是用于从输入设备(如键盘)读取数据和向输出设备(如显示器)写入数据的对象。C++ 标准库提供了以下主要 I/O 流:
cin
:标准输入流,用于从键盘读取数据cout
:标准输出流,用于向显示器写入数据cerr
:标准错误流,用于向显示器写入错误消息ifstream
:文件输入流,用于从文件读取数据ofstream
:文件输出流,用于向文件写入数据
示例
1 |
|
在这个示例中,我们创建了一个 vector
,使用 sort
算法对它进行排序,然后使用 I/O 流打印排序后的 vector
。
指针、引用和内存管理
指针
指针是一个变量,它存储另一个变量的地址。通过使用指针,我们可以间接访问和修改其他变量的值。指针用 *
(星号)表示。
引用
引用是另一个变量的别名。与指针不同,引用必须在声明时初始化,并且不能重新绑定到其他变量。引用用 &
(地址)符号表示。
内存管理
在 C++ 中,程序员负责管理内存。这意味着程序员必须分配和释放内存。如果不正确地管理内存,可能会导致内存泄漏或段错误。
动态内存分配
动态内存分配允许程序员在运行时分配内存。可以使用 new
运算符分配内存,并使用 delete
运算符释放内存。
智能指针
智能指针是 C++ 11 中引入的特殊类型的指针,它可以自动管理内存。智能指针跟踪它们指向的对象,并在对象不再需要时自动释放内存。
示例
1 | // 指针示例 |
指针、引用和内存管理之间的区别
特征 | 指针 | 引用 | 内存管理 |
---|---|---|---|
语法 | * |
& |
new 、delete |
初始化 | 可以延迟初始化 | 必须在声明时初始化 | 无需初始化 |
可重新绑定 | 可以重新绑定到其他变量 | 不能重新绑定到其他变量 | 无需重新绑定 |
内存管理 | 程序员负责管理内存 | 程序员负责管理内存 | 程序员或智能指针负责管理内存 |
C++ 模板和泛型编程
C++ 模板
C++ 模板是一种创建可重用代码的方法,而无需为每种数据类型编写特定版本的代码。模板使用尖括号 <>
表示,其中包含类型参数。
泛型编程
泛型编程是一种编写代码的方法,使代码独立于数据类型。通过使用模板,我们可以创建可以在各种数据类型上工作的算法和数据结构。
模板语法
1 | template <typename T> // T 是类型参数 |
泛型算法示例
1 | template <typename T> |
这个函数可以用于任何数据类型,因为类型参数 T
是通用的。
模板类示例
1 | template <typename T> |
这个类可以存储任何数据类型的元素,因为类型参数 T
是通用的。
模板的优点
- 代码重用:模板允许我们创建可重用代码,而无需为每种数据类型编写特定版本的代码。
- 类型安全性:模板确保在编译时检查类型,从而防止类型错误。
- 性能:模板可以生成针对特定数据类型优化的代码,从而提高性能。
模板的缺点
- 编译时间:模板的编译时间可能比非模板代码更长。
- 代码复杂性:模板代码可能比非模板代码更复杂,这可能会使调试变得困难。
异常处理、多线程和并发
异常处理
异常处理是一种处理运行时错误的方法。当发生错误时,会引发异常,程序可以捕获并处理该异常。
异常处理语法
1 | try { |
多线程和并发
多线程和并发允许程序同时执行多个任务。线程是程序执行的独立路径,并发是同时执行多个线程的过程。
多线程和并发的好处
- 提高性能:多线程和并发可以提高程序性能,尤其是在处理大量数据或执行并行任务时。
- 响应能力:多线程和并发可以使程序对用户输入和事件更具响应性。
- 可扩展性:多线程和并发可以使程序更具可扩展性,因为它允许程序根据需要利用更多处理核心。
多线程和并发的实现
C++ 中有多种创建和管理线程的方法,包括:
- POSIX 线程 (pthreads):一种用于创建和管理线程的跨平台 API。
- C++11 线程:C++11 标准库中引入的用于创建和管理线程的本机支持。
并发模型
有多种并发模型可用于协调线程之间的交互,包括:
- 互斥锁:一种同步机制,它允许一次只有一个线程访问共享资源。
- 条件变量:一种同步机制,它允许线程等待特定条件满足。
- 原子操作:一种特殊类型的操作,它以原子方式执行,确保在多个线程同时访问共享资源时不会出现数据竞争。
设计模式和最佳实践
设计模式
设计模式是经过验证的、可重复使用的解决方案,用于解决软件设计中常见的挑战。它们提供了一种通用语言来讨论和理解软件架构,并有助于提高代码的可重用性、可维护性和可扩展性。
一些常见的 C++ 设计模式包括:
- 单例模式:确保类只有一个实例。
- 工厂模式:创建对象的工厂方法。
- 观察者模式:允许对象订阅并接收来自其他对象的事件通知。
- 策略模式:允许算法或行为在运行时更改。
- 适配器模式:使不兼容的接口能够一起工作。
最佳实践
遵循最佳实践可以帮助编写高质量、可维护和可扩展的 C++ 代码。一些 C++ 最佳实践包括:
- 使用现代 C++:使用 C++11 和更高版本中引入的现代 C++ 特性,例如智能指针、lambda 表达式和范围 for 循环。
- 遵循编码准则:遵循一致的编码准则,例如缩进、命名约定和注释。
- 编写可测试的代码:编写易于测试的代码,使用单元测试框架和模拟来验证其正确性。
- 使用异常处理:使用异常处理来处理错误条件,而不是返回错误代码。
- 管理内存:正确管理内存,使用智能指针或遵循资源获取即初始化 (RAII) 原则。
- 优化性能:分析代码的性能并进行优化,例如使用缓存、并行性和数据结构。
- 进行代码审查:定期进行代码审查,以识别错误、改进设计并共享知识。
没写完,什么时候想起来了再接着写
或者可以去看🔜 C++文档