一、范围for语句
范围for语句可以遍历容器或其他序列的所有元素。
语法:
for (declaration : expression)
statement
//expression表示的必须是一个序列。
//declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型。
//statement是一条单独的语句或一个块。
每次迭代都会重新定义循环控制变量,并将其初始化成序列的下一个值,之后才会执行statement。
例:
vector<int> v={1,2,3,4,5,6,7,8,9};
for(auto i:v)
cout<<i<<endl;
//遍历容器v中的元素并打印。
二、throw表达式和异常处理
异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接及遇到意外输入等。
当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。此时,检测出问题的部分应该发出某种信号以表明程序遇到了故障,无法继续下去了,而且信号的发出方无须知道故障将在何处得到解决。一旦发出异常信号,检测出问题的部分也就完成了任务。
若程序中含有可能引发异常的代码,那么通常也会有专门的代码处理问题。例如,若程序的问题是输入无效,则异常处理部分可能会要求用户重新输入正确的数据;若丢失了数据库连接,会发出报警信息。
异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。
异常处理包括:
1.throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题。
2.try语句块,异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理。
一套异常类,用于在throw表达式和相关的catch子句之间传递异常的具体信息。
(一)throw表达式
throw表达式包括关键字throw和紧跟其后的一个表达式,其中,表达式的类型就是抛出的异常类型。
throw表达式后紧跟一个分号,从而构成一条表达式语句。
例:
if(item1.isbn()!=item2.isbn())
throw runtime_error("Data must refer to same ISBN");
runtime_error是标准库异常类型的一种,定义在stdexcept头文件中。 必须初始化runtime_error的对象,方式是给它提供一个string对象或者一个C风格的字符串,这个字符串中有一些关于异常的辅助信息。
(二)try语句块
通用语法形式:
try{
program-statements
} catch(exception-declaration){
handler-statements
}
catch(exception-declaration){
handler-statements
}...
//catch子句包括三部分:
//1.关键字catch
//2.括号内一个对象的声明
//3.一个块
catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。
try语句块中的program-statements组成程序的正常逻辑,像其他任何块一样,program-statements可以有包括声明在内的任意C++语句。一如往常,try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。
try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。
例:
while(cin>>item1>>item2)
{
try
{
//...//执行添加两个Sales_item对象的代码
//若添加失败,代码抛出一个runtime_error异常。
}catch(runtime_error)
{
//提醒用户两个ISBN必须一致,询问是否重新输入
cout<<err.what()<<"\nTry Again? Enter y or n"<<endl;
char c;
cin>>c;
if(!cin||c=='n')
break;//跳出while循环
}
}
每个标准库异常类都定义了名为what的成员函数,这些函数没有参数,返回值是C风格字符串(即const char*)。
其中,runtime_error的what成员返回的是初始化一个具体对象时所用的string对象的副本。
三、函数在寻找代码的过程中退出
在复杂系统中,程序在遇到抛出异常的代码前,其执行路径可能已经经过了多个try语句块。例如,一个try语句块可能调用了包含另一个try语句块的函数,新的try语句块可能调用了包含又一个try语句块的新函数,以此类推。
寻找代码的过程与函数调用链刚好相反。当异常被抛出时,首先搜索抛出该异常的函数。若未找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。若还是未找到匹配的catch子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。
若最终还是没能找到任何匹配的catch子句,程序转到名为terminate的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。
对于那些没有任何try语句块定义的异常,也按照类似的方式处理:毕竟,没有try语句块也就意味着没有匹配的catch子句。若一段程序没有try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。
四、标准异常
C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用。
C++标准库定义的异常类分别定义在4个头文件中:
1.exception头文件定义了最通用的异常类exception。它只报告异常的发生,不提供任何额外信息。
2.sdexcept头文件定义了几种常用的异常类。
3.new头文件定义了bad_alloc异常类型。
4. type_info头文件定义了bad_cast异常类型。
exception | 最常见的问题 |
runtime_error | 只有在运行时才能检测出的问题 |
range_error | 运行时错误:生成的结果超出了有意义的值域范围 |
overflow_error | 运行时错误:计算上溢 |
underflow_error | 运行时错误:计算下溢 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误:参数对应的结果值不存在 |
invalid_argument | 逻辑错误:无效参数 |
length_error | 逻辑错误:试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误:使用一个超出有效范围的值 |
只能以默认初始化的方式初始化exception、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。
其他异常类型则刚好相反,应该使用string对象或者C风格字符串初始化这些类型的对象,但不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,改初始值含有错误相关的信息。
异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char*。该字符串的目的是提供关于异常的一些文本信息。
what函数返回的C风格字符串的内容与异常对象的类型有关。若异常类型有一个字符串初始值,则what返回该字符串。对于其他无初始值的异常类型来说,what返回的内容由编译器决定。