C++冒险攻略(持续更新中。。。)
ShyButHandsome 人气:0
[我的C++冒险之旅](https://github.com/ShyButHandsome/OIer)
## 绪论
### 计算机系统基本概念
#### 计算机硬件
![计算机硬件](http://sc0.ykt.io/ue_i/20200303/1234759975939739648.png)
#### 计算机程序语言
- 计算机解决问题是**程序控制**的
- 程序就是**操作步骤**
- 程序要使用**语言来表达**
#### 机器语言
- 计算机**能识别**的是机器语言
- 机器语言指令是由0和1编码的
- 例如:加法指令可能是"0001"
#### 计算机指令系统
- 机器硬件能够识别的语言(机器语言)的**集合**;
- 它是软件和硬件的主要界面。
#### 计算软件
- 是一系列按照特定顺序组织的计算机数据和指令的集合。一般来讲软件被划分为**系统软件、应用软件**和介于这两者之间的**中间件**;
- 软件包括程序和**文档**。
> 编写大型程序时,尤其要注意编写文档
#### 计算机程序
- 指令的序列;
- 描述解决问题的方法和数据。
### 计算机语言和程序设计方法
#### 最初的计算机语言——机器语言
- 由二进制代码构成
- 计算机硬件可以识别
- 可以表示简单的操作
- 例如:加法、减法、数据移动等等
#### 汇编语言
- 将机器指令映射为助记符
- 如ADD、SUB、mov等;
- 抽象层次低,需要考虑机器细节。
#### 高级语言
- 关键字、语句容易理解;
- 有含义的数据命名和算式;
- 抽象层次较高;
- 例如,算式:a+b+chttps://img.qb5200.com/download-x/d
- 屏蔽了机器的细节:
- 例如,这样显示计算结果:
- cout << a + b + c / d
#### C++语言
- 是高级语言
- 支持面向对象的观点和方法
- 将客观事物看做对象
- 对象间通过消息传送进行沟通
- 支持分类和抽象
#### 面向过程的程序设计方法
- 机器语言、汇编语言、高级语言都支持;
- 最初的目的:用于数学计算;
- 主要工作:设计求解问题的过程。
- 大型复杂的软件难以用面向过程的方式编写
#### 面向对象的程序设计方法
- 由面向对象的高级语言支持;
- 一个系统由对象构成;
- 对象之间通过消息进行通信。
### 面向对象的基本概念
#### 对象
- 一般意义上的对象:现实世界中实际存在的事物。
- 面向对象方法中的对象:程序中用来描述客观事物的实体。
#### 抽象与分类
- 分类依据的原则——抽象;
- 抽象出同一类对象的共同属性和行为形成类;
- 类与对象是类型与实例的关系。
#### 封装
- 隐蔽对象的内部细节;
- 对外形成一个边界;
- 只保留有限的对外接口;
- 使用方便、安全性好。
#### 继承
- 意义在于软件复用;
- 改造、扩展已有类形成新的类。
#### 多态
- 同样的消息作用在不同对象上,可以引起不同的行为。
### 程序的开发过程
#### 程序
- 源程序:
- 用源语言写的,有待翻译的程序;
- 目标程序:
- 源程序通过翻译程序加工以后生成的机器语言程序;
- 可执行程序:
- 连接目标程序以及库中的某些文件,生成的一个可执行文件;
- 例如:Windows系统平台上的.EXE文件。
#### 三种不同类型的翻译程序
- 汇编程序:
- 将汇编语言源程序翻译成目标程序;
- 编译程序:
- 将高级语言源程序翻译成目标程序;
- 解释程序:
- 将高级语言源程序翻译成机器指令,边翻译边执行。
#### C++程序的开发过程
- 算法与数据结构设计;
- 源程序编辑;
- 编译;
- 连接;
- 测试;
- 调试。
### 计算机中的信息与存储单位
#### 计算机的基本功能
- 算术运算;
- 逻辑运算。
#### 计算机中信息:
- 控制信息——指挥计算机操作;
- 数据信息——计算机程序加工的对象。
![数据信息](http://sc0.ykt.io/ue_i/20191116/1195526480034140160.png)
#### 信息的存储单位
- 位(bit,b):数据的最小单位,表示一位二进制信息;
- 字节(byte,B):八位二进制数字组成(1 byte = 8 bit);
- 千字节 1 KB = 1024 B;
- 兆字节 1 MB = 1024 K;
- 吉字节 1 GB = 1024 M。
### 计算机的数字系统
#### 计算机的数字系统
- 二进制系统;
- 基本符号:0、1。
#### 程序中常用的数制:
![程序中常用进制](http://sc0.ykt.io/ue_i/20191116/1195543238736482304.png)
- 制转换为十进制:
- 各位数字与它的权相乘,其积相加,例如:
- (11111111.11)2
=1×27+1×26+1×25+1×24+1×23+1×22+1×21+1×20+1×2-1+1×2-2
=(255.75)10
#### 十进制整数转换为R 进制整数:
- “除以R取余”法。
- 6810=10001002
![68=1000100](http://sc0.ykt.io/ue_i/20191116/1195543921728557056.png)
#### 十进制小数→ R 进制小数:
- “乘 以R 取整”法。
- 0.312510 = 0.01012
![68=1000100](http://sc0.ykt.io/ue_i/20191116/1195544082131324928.png)
#### 二、八、十六进制的相互转换
- 1位八进制数相当于3位二进制数;
- 1位十六进制数相当于4位二进制数,例如:
- (1011010.10)2=(001 011 010 .100)2=(132.4)8
- (1011010.10)2=(0101 1010 .1000)2=(5A.8)16
- (F7)16=(1111 0111)2=(11110111)2
### 数据在计算机中的编码表示
#### 二进制数的编码表示
- 需要解决的问题:负数如何表示?
- 最容易想到的方案:
- 0:表示“+”号;
- 1:表示“-”号。
- 原码
- "符号 ── 绝对值"表示的编码
- 例如:
![原码](http://sc0.ykt.io/ue_i/20191116/1195544525414731776.png)
- 原码的缺点:
- 零的表示不惟一
- [+0]原 =000...0
- [-0]原 =100...0
- 进行四则运算时,符号位须单独处理,运算规则复杂。
- 补码
- 符号位可作为数值参加运算;
- 减法运算可转换为加法运算;
- 0的表示唯一。
- 补码的原理
- 模数:
- n位二进制整数的模数为 2n
- n位二进制小数的模数为 2。
- 补数:
- 一个数减去另一个数(加一个负数),等于第一个数加第二个数的补数,
- 例(时钟指针): 8+(-2)=8+10 ( mod 12 )=6;
- 一个二进制负数可用其模数与真值做加法 (模减去该数的绝对值) 求得其补码,
- 例(时钟指针):-2+12=10。
- 补码的计算
- 借助于“反码”作为中间码;
- 负数的反码与原码有如下关系:
- 位不变(仍用1表示),其余各位取反(0变1,1变0),例如:
- X=-1100110
- [X]原 =1 1100110
- [X]反 =1 0011001
- 正数的反码与原码表示相同,正数的补码与原码相同;
- 反码只是求补码时的中间码;
- 负数的补码由该数反码的末位加 1 求得。
- 对补码再求补即得到原码。
- 补码的优点:
- 0的表示唯一;
- 符号位可作为数值参加运算;
- 补码运算的结果仍为补码。
#### 实数的浮点表示
- 计算机中通常采用浮点方式表示小数;
- 实数 N 用浮点形式可表示为: N = M × 2E
- E:2的幂,N:阶码;
- M:N的尾数。
#### 字符在计算机中的表示
- 字符在计算机中是通过编码表示的;
- 例如:
- ASCII码是一种常用的西文字符编码:用7位二进制数表示一个字符,最多可以表示27=128个字符;
- 《GB 18030-2005 信息技术 中文编码字符集》是中国国家标准。
## C++简单程序设计
### C++的特点和程序实例
#### C++的产生和发展
- 从C语言发展演变而来,最初被称为"带类的C";
- 1983年正式取名为C++;
- **1998年**11月被国际标准化组织(ISO)批准为国际标准;
- **2003年**10月15日发布**第2版C++标准**ISO/IEC 14882:2003;
- **2011年**8月12日ISO公布了第三版C++标准**C++11**,包含核心语言的新机能、扩展C++标准程序库。
- 2014年8月18日ISO公布了C++14,其正式名称为"International Standard ISO/IEC 14882:2014(E) Programming Language C++"。
- C++14作为C++11的一个小扩展,主要提供漏洞修复和小的改进。
#### C++的特点
- 兼容C,支持**面向过程**的程序设计;
- 支持**面向对象**的方法;
- 支持**泛型**程序设计方法。
#### 命名空间
避免命名冲突
std是C++标准库的命名空间(namespace)名
using namespace std表示打开std命名空间
```cpp
//例2_1.cpp
#include
using namespace std;
int main() {
cout << "Hello!" << endl;
cout << "Welcome to c++!" << endl;
return 0;
}
```
```text
Hello!
Welcome to c++!
```
### C++字符集和词法记号
#### 字符集
![字符集](http://sc0.ykt.io/ue_i/20200303/1234771740043907072.png)
#### 词法记号
- 关键字
- **C++预定义**的单词
- 标识符
- **程序员声明**的单词,它命名程序正文中的一些实体
- 文字
- 在程序中**直接使用符号**表示的数据
- 分隔符
- 用于分隔各个词法记号或程序正文
> ()
> {}
> ,
> :
> ;
- 运算符(操作符)
- 用于**实现各种运算**的符号
- 空白符
- 空格、制表符(TAB键产生的字符)、垂直制表符、换行符、回车符和注释的总称
#### 标识符的构成规则
- 以大写字母、小写字母或下划线(_)开始。
- 可以由以大写字母、小写字母、下划线(_)或数字0~9组成。
- 大写字母和小写字母代表不同的标识符。
- 不能是C++关键字或操作符。
### 基本数据类型、常量、变量
#### C++能够处理的基本数据类型
- 整数类型;
- 浮点数类型;
- 字符类型;
- 布尔类型。
#### 程序中的数据
- 常量
- 在源程序中直接写明的数据;
- 其值在整个程序运行期间**不可改变**。
- 变量
- 在程序运行过程中**允许改变**的数据。
#### 整数类型
- 基本的整数类型:int
- 按**符号**分
- 符号的(signed)
- 无符号的(unsigned)
- 按照**数据范围**分
- 短整数(short)
- 长整数(long)
- 长长整数( long long )
- ISO C++标准并没有明确规定每种数据类型的字节数和取值范围,它只是规定它们之间的字节数大小顺序满足:
> (signed/unsigned)signed char ≤(unsigned) short int ≤(unsigned) int ≤(unsigned) long int ≤ long long int
#### 字符类型(char)
- 容纳**单个字符**的编码;
- 实质上存储的也是**整数**。
#### 浮点数类型
- 单精度(float)
- 双精度(double)
- 扩展精度(long double)
注意:浮点数在计算机中是近似储存的,不能直接比较两个浮点数的大小。
#### 字符串类型
- 有字符串常量
- 基本类型中**没有字符串变量**
- 采用字符数组存储字符串(C风格的字符串)
- 标准C++类库中的String类(C++风格的字符串)
#### 布尔类型(bool)
- 只有两个值:true(真) 、false(假)
- 常用来表示关系比较、相等比较或逻辑运算的结果
#### 各基本类型的取值范围
![各基本类型取值范围](http://sc0.ykt.io/ue_i/20191116/1195545121131728896.png)
#### 常量
- 在程序运行的整个过程中其值**始终不可改变**的量;
- 直接使用符号(文字)表示的值;
- 例如:12,3.5,'A'都是常量。
#### 整数常量
- 以文字形式出现的整数;
- 十进制
- 若干个0~9的数字,但数字部分**不能以0开头**,正数前边的正号可以省略。
- 八进制
- **前导0**+若干个0~7的数字。
- 十六进制
- **前导0x**+若干个0~9的数字及A~F的字母(大小写均可)。
- 后缀
- 后缀L(或l)表示类型至少是long,
- 后缀LL(或ll)表示类型是long long,
- 后缀U(或u)表示unsigned类型。
#### 浮点数常量
- 以文字形式出现的实数;
- 一般形式:
- 例如,12.5,-12.5等。
- 指数形式:
- 例如,0.345E+2,-34.4E-3;
- 整数部分和小数部分可以省略其一。
- 浮点常量**默认为double型**,如果后缀F(或f)可以使其成为float型,例如:12.3f。
#### 字符常量
- 单引号括起来的一个字符,如:'a'、'D'、'?'、'$';
- C++转义字符列表(用于在程序中表示不可显示字符)
![C++转义字符列表](http://sc0.ykt.io/ue_i/20191116/1195545320226951168.png)
#### C风格字符串常量
- 一对**双引号**括起来的字符序列
- 在内存中按串中字符的排列次序顺序存放,每个字符占一个字节
- **在末尾添加**'\0'作为结尾标记
例:
![字符串储存规则](http://sc0.ykt.io/ue_i/20191116/1195545609008975872.png)
通过添加**前缀**可以改变字符常量或者字符串常量的类型,前缀及其含义如下表所示:
![前缀](http://sc0.ykt.io/ue_i/20191116/1195545753997676544.png)
#### 变量
在程序的运行过程中,其值可变的量
- 变量定义
- 数据类型 变量名1, 变量名2, ..., 变量名n;
```cpp
int a, b, ...;
````
- 初始化
- C++语言中提供了多种初始化方式;
- 例如:
```cpp
int a = 0;
int a(0);
int a = {0};
int a{0};
```
其中使用大括号的初始化方式称为**列表初始化**,列表初始化时**不允许信息的丢失**。例如用double值初始化int变量,就会造成数据丢失。
#### 符号常量
- 常量定义语句的形式为:
- const 数据类型说明符 常量名 = 常量值;
```cpp
const double PI = 3.1415926;
```
- 或:
- 数据类型说明符 const 常量名=常量值;
```cpp
float const PI = 3.1415926;
```
符号常量在定义时**一定要初始化**,在程序中间不能改变其值。
### 算数运算和赋值运算
#### 算术运算
- 基本算数运算符
- '+' '-' '*' '/'(若整数相除,结果舍去小数部分取整)
- '%' 取余,操作数为整数
- 优先级和结合性
- 先乘除(包括%),后加减,同级自左向右
- '++'自增 '--'自减
- 'i++' 是先将i进行其他运算,再+1
- '--i' 是先-1,再进行其它运算
#### 赋值运算
将值赋给变量
赋值运算符 '='
- 赋值表达式:
- 用赋值运算符连接的表达式
- 例如:
```cpp
n = 5;
n = n + 5;
```
- 表达式的值
- 赋值运算符左边对象被赋值后的值
```cpp
cout << (n = 5) // '<<'的优先级更高
```
```text
5
```
- 表达式的类型
- 赋值运算符左边对象的类型
- 复合赋值运算符
- '+=' '-=' '*=' '/=' '%=' '<<=' '>>=' '&=' '^=' '|='
- 例如:
```cpp
a += 3 // 等价于 a = a + 3
x *= y + 8 // 等价于 x = x * (y + 8), 带了括号
```
### 逗号运算、关系运算、逻辑运算和条件运算
#### 逗号运算和逗号表达式
- 格式
- 表达式1,表达式2
- 求解顺序及结果
- 先求解表达式1,再求解表达式2
- 最终结果为表达式2的值
- 例
```cpp
a = 3 * 5 , a * 4 最终结果为60
```
#### 关系运算与关系表达式
- 关系运算是比较简单的一种逻辑运算,优先次序为:
![关系运算优先次序](http://sc0.ykt.io/ue_i/20191116/1195546687456808960.png)
- 关系表达式是一种最简单的逻辑表达式
- 其结果类型为 bool,值只能为 true 或false。
- 例如:
```cpp
a > b,c <= a + b,x + y == 3
```
#### 逻辑运算与逻辑表达式
- 逻辑运算符
```text
!(非) &&(与) ||(或)
优先次序: 高 → 低
```text
- 逻辑运算结果类型:bool,值只能为 true 或false
- 逻辑表达式
- 例如:
- (a > b) && (x > y)
- “&&”的运算规则
- 两侧表达式都为真,结果为真;
- 有一侧表达式为假,结果为假。
- “&&” 的“短路特性”
```cpp
表达式1 && 表达式2
```
- 执行顺序
1. 先求解表达式1
2. 若表达式1的值为false,则最终结果为false,不再求解表达式2
3. 若表达式1的结果为true,则求解表达式2,以表达式2的结果作为最终结果
- “||”的运算规则
- 两侧表达式都为假,结果为假;
- 有一侧表达式为真,结果为真。
- “||” 的“短路特性”
```cpp
表达式1 || 表达式2
```
- 执行顺序
1. 先求解表达式1
2. 若表达式1的值为true,则最终结果为true,不再求解表达式2
3. 若表达式1的结果为false,则求解表达式2,以表达式2的结果作为最终结果
#### 条件运算符与条件表达式
- 一般形式
```cpp
表达式1?表达式2:表达式3
```
表达式1 必须是bool 类型
- 执行顺序
1. 先求解表达式1,
2. 若表达式1的值为true,则求解表达式2,表达式2的值为最终结果
3. 若表达式1的值为false,则求解表达式3,表达式3的值为最终结果
- 条件运算符优先级高于赋值运算符,低于逻辑运算符
- 例
![三类运算符](http://sc0.ykt.io/ue_i/20191116/1195546854079729664.png)
- 表达式1是bool类型,
- 表达式2、3的类型可以不同,
- 条件表达式的最终类型为2 和3 中较高的类型。
### sizeof运算、位运算
#### sizeof运算
- 语法形式
- sizeof (类型名) 或 sizeof 表达式
- 结果值:
- “类型名”所指定的类型,
- 或“表达式”的结果类型所占的字节数。
- 例:
```cpp
sizeof(short);
sizeof x;
```
#### 位运算——按位与(&)
- 运算规则
- 将两个运算量的每一个位进行逻辑与操作
- 举例:计算3 & 5
![3&5](http://sc0.ykt.io/ue_i/20191116/1195547446013464576.png)
- 用途:
- 将某一位置0,其他位不变。
- 例如:
- 将char型变量a的最低位置0:
```cpp
a = a & 0xfe; // 0xfe:1111 1110
```
- 取指定位。
- 例如:
- 有char c; int a; 取出a的低字节,置于c中:
```cpp
c=a & 0xff; // 0xff:1111 1111
```
#### 位运算——按位或(|)
- 运算规则
- 将两个运算量的每一个位进行逻辑或操作
- 举例:计算3 | 5
![3|5](http://sc0.ykt.io/ue_i/20191116/1195547446013464576.png)
- 用途:
- 将某些位置1,其他位不变。
- 例如:将 int 型变量 a 的低字节置 1 :
```cpp
a = a | 0xff;
```
#### 位运算——按位异或(^)
- 运算规则
- 两个操作数进行异或:
- 若对应位相同,则结果该位为 0,
- 若对应位不同,则结果该位为 1,
- 举例:计算 071^052
![071^052](http://sc0.ykt.io/ue_i/20191116/1195547581837611008.png)
- 用途举例:使特定位翻转(与0异或保持原值,与1异或取反)
- 例如:要使 01111010 低四位翻转:
![使011111010低四位翻转](http://sc0.ykt.io/ue_i/20191116/1195547727174438912.png)
#### 位运算——取反(~)
- 运算规则
- 单目运算符,对一个二进制数按位取反。
- 例:
```text
025:0000000000010101
~025:1111111111101010
```
#### 位运算——移位(<<、>>)
- 左移运算(<<)
- 左移后:
- 低位:补0
- 高位:舍弃。
- 右移运算(>>)
- 右移后:
- 低位:舍弃
- 高位:
- 无符号数:补0
- 有符号数:补“符号位”
### 运算优先级、类型转换
#### 运算符优先级
| 优先级 | 运算符 | 结合性 |
|:-:|:-:|:-:|
| 1 | [ ] ( ) . –> 后置++ 后置–– | 左→右|
| 2 | 前置++ 前置–– sizeof & * +(正号)–(负号)~ ! | 右→左|
| 3 |(强制转换类型)| 右→左|
| 4 | .* ->* | 左→右|
| 5 | * / % | 左→右 |
| 6 | + – | 左→右|
| 7 | << >> | 左→右|
| 8 | < > <= >= | 左→右 |
| 9 | == != | 左→右 |
| 10 | & | 左→右 |
| 11 | ^ | 左→右 |
| 12 | `|` | 左→右 |
| 13 | && | 左→右 |
| 14 | `||` | 左→右 |
| 15 | ? : | 右→左 |
| 16 | = *= /= %= += –= <<= >>=&= ^= `|=` | 右→左|
| 17 | , | 左→右 |
#### 混合运算时数据类型的转换
- 一些二元运算符(算术运算符、关系运算符、逻辑运算符、位运算符和赋值运算符)要求两个操作数的类型一致。
- 在算术运算和关系运算中如果参与运算的操作数类型不一致,编译系统会自动对数据进行转换(即隐含转换),基本原则是将低类型数据转换为高类型数据。
![隐式类型转换](https://images.cnblogs.com/cnblogs_com/ShyButHandsome/1664438/t_200308105623temp.png)
- 将一个非布尔类型的算术值赋给布尔类型时,算术值为0则结果为false,否则结果为true。
- 将一个布尔值赋给非布尔类型时,布尔值为false则结果为0,布尔值为true则结果为1
- 将一个浮点数赋给整数类型时,结果值将只保留浮点数中的整数部分,小数部分将丢失。
- 将一个整数值赋给浮点类型时,小数部分记为0。如果整数所占的空间超过了浮点类型的容量,精度可能有损失。
#### 混合运算时数据类型的转换——显式转换
- 显式类型转换的作用是将表达式的结果类型转换为类型说明符所指定的类型。
- 语法形式
- 类型说明符(表达式)
- (类型说明符)表达式
- 类型转换操作符<类型说明符>(表达式)
- 类型转换操作符可以是:
```cpp
const_cast
dynamic_cast
reinterpret_cast
static_cast
```
- 例:
```cpp
// 三种完全等价
int(z)
(int)z
static_cast(z)
```
加载全部内容