【C++】【C++ Primer】5-语句
1 简单语句
1.1 表达式语句
在表达式末尾加上分号就是表达式语句。
表达式语句的作用是执行表达式,并丢弃求值结果。
1.2 空语句
空语句只含有一个单独的分号。
如果编程时语法上需要一条语句,但逻辑上不需要,就应使用空语句。譬如while循环。
使用空语句时应加上注释,以便让其他人知道此处是有意使用空语句。
1.3 复合语句(块)
复合语句也称作块,是指用花括号括起来的语句和声明序列。一个块就是一个作用域。
如果在程序的某个地方,语法上需要一条语句,但逻辑上需要多条语句,则应使用复合语句。
空块是指内部没有任何语句的一对花括号,作用等价于空语句。
2 语句作用域
可以在if、switch、while、for语句的控制结构内定义变量。定义在控制结构中的变量只在相应语句的内部可见,一旦语句结束,变量就超出其作用范围了。如果其他代码也要访问控制变量,则变量应定义在语句外部。
3 条件语句
3.1 if语句
此处无需赘述
3.2 switch语句
此处无需赘述
4 迭代语句
4.1 while语句
此处无需赘述
4.2 传统for语句
此处无需赘述
4.3 范围for语句
范围for语句可以遍历容器或其他序列的所有元素,语法格式如下:
for (declaration : expression) {
statement
}
expression必须是一个序列,这些类型的共同特点是拥有能返回迭代器的begin和end成员。譬如:
- 花括号括起的初始值列表
- 数组
- vector
- string
declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型。最简单的方法就是使用auto类型说明符。如果要修改序列本身,要将循环变量声明为引用类型。
不能通过范围for语句增删expression容器的元素,因为范围for语句中预存了end()的值。
4.4 do while语句
do while语句条件后面要加上分号,表示语句结束。
5 跳转语句
C++提供4种跳转语句:
- break
- continue
- goto
- return
5.1 break语句
break语句只能出现在迭代语句(while、do while、for)或switch语句内部。作用是终止离它最近的迭代语句或switch语句,并从这些语句之后的第一条语句开始继续执行。
5.2 continue语句
continue语句只能出现在迭代语句(while、do while、for)内部。作用是终止离它最近的循环中的本次迭代,并立即开始下一次迭代。
和break语句不同,continue不能应用在switch中,除非这个switch嵌套在迭代语句中。
5.3 goto语句
goto语句的作用是从goto语句无条件跳转到同一函数内的另一条语句。
goto语句的语法格式:
goto label:
label用于表示一条语句。带标签语句是一种特殊的语句,在它之前有一个标识符及一个冒号:
end: return; // 带标签语句,可以作为goto的目标
标签标识符独立于其他变量或其他标识符的名字。因此,标签标示符可以和程序中其他实体的标示符重名,而不会产生干扰。
6 try语句块和异常处理
异常是指运行时的反常行为。
当程序某部分检测到一个它无法处理的问题时,就应发出某种信号,表明程序遇到故障,无法继续下去。信号的发出方无需知道故障将在何处得到解决,一旦发出信号,它的任务就完成了。如果程序中含有可能引发异常的代码,通常也会有专门的代码处理问题。
异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。C++语言中,异常处理包括:
- throw表达式:异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们称之为throw引发了异常
- try语句块:异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。try语句块中抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,也被称作异常处理代码
- 异常类:用于在throw表达式和相关的catch子句之间传递异常的具体信息
6.1 throw表达式
程序的异常检测部分使用throw表达式引发一个异常。throw表达式包含关键字throw和紧随其后的表达式,表达式的类型就是抛出的异常类型。
if (item1.isbn() != item2.isbn()) {
throw runtime_error("Data must refer to same ISBN");
}
抛出异常将终止当前的函数,并将控制权转移给能处理该异常的代码。
6.2 try语句块
try语句块语法形式如下:
try {
program-statements
} catch (exception-declaration) {
handler-statements
} catch (exception-declaration) {
handler-statements
} // ...
try语句块中的program-statements组成程序的正常逻辑,但try语句块内声明的变量在块外部无法访问(catch子句中也不行)。
catch子句包括三部分:
- 关键字catch
- 括号内的异常声明(对象,可能未命名)
- 块
选中某个catch子句处理异常后,执行与之对应的块。catch执行完成,程序就跳转到try语句块最后一个catch子句之后的代码继续执行。
6.2.1 异常处理代码
我们要把可能出现异常的代码放在try语句块中。try语句块对应的catch子句负责处理异常。
6.2.2 函数在寻找处理代码的过程中退出
对于复杂系统,程序在遇到抛出异常的代码之前,其执行路径可能已经经过了多个try语句块。简而言之,就是try套着try。
寻找异常处理代码的过程和函数调用过程相反。异常被抛出后,首先搜索抛出该异常的函数,如果没有匹配的catch子句,则终止该函数,在调用该函数的函数中继续寻找。以此类推,沿着函数的执行路径逐层回退,知道找到适当类型的catch子句为止。
如果最终没有找到对应catch子句,或一段程序没有try语句块且发生了异常,则程序转到名为terminate的标准库函数。该函数的行为与系统有关,通常是导致程序非正常退出。
6.3 标准异常
C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用。它们定义在4个头文件中:
- exception头文件:定义最通用的异常类exception。它只报告异常的发生,不提供任何额外信息。
- stdexcept头文件:定义了几种常用的异常类。
- new头文件:定义了bad_alloc异常类型。
- type_info头文件:定义了bad_cast异常类型
stdexcept定义的异常类 | |
---|---|
exception | 最常见的问题 |
runtime_error | 只有在运行时才能检测出的问题 |
range_error | 运行时错误:生成的结果超出了有意义的值域范围 |
overflow_error | 运行时错误:计算上溢 |
underflow_error | 运行时错误:计算下溢 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误:参数对应的结果值不存在 |
invalid_argument | 逻辑错误:无效参数 |
length_error | 逻辑错误:试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误:使用一个超出有效范围的值 |
标准库类型只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。
6.3.1 标准库类型的初始化
exception、bad_alloc、bad_cast这三个异常类只能默认初始化。其他异常类必须用string对象或C风格字符串初始化,目的是提供关于异常的信息。
每个标准库异常类都定义了名为what的函数,这些函数没有参数,返回值是C风格字符串(const char *)。字符串的内容与异常对象的类型有关。用字符串初始化的异常类型返回该字符串,默认初始化的异常类返回的内容由编译器决定。
已完成