0x04_语句

语句

switch语句

switch的执行流程有可能会跨过某些case标签。如果程序跳转到了某个特定的case,则switch结构中该case标签之前的部分会被忽略掉。

如果在某处一个带有初值的变量位于作用域之外,在另一处该变量位于作用域之内,则从前一处跳转到后一处的行为是非法行为。即不允许跨过变量的初始化语句直接跳转到该变量作用域的另一个位置。

case true:
// 因为程序的执行流程可能绕开下面的初始化语句,所以该switch语句不合法
string file_name; // 错误:控制流绕过一个隐式初始化的变量
int jval = 0; // 错误:控制流绕过一个显式初始化的变量
int jval; // 正确:因为jval没有初始化
break;
case false:
jval = next_num(); // 正确:给jval赋一个值
if (file_name.empty()) // file_name在作用域内,但是没有被初始化
// ...

C++不允许使用未初始化的变量,而初始化操作和定义变量对于编译器来说是不同的事情。初始化操作是在运行时才会被调用的语句,是可以被case跳转屏蔽的语句,而定义则是在执行case跳转前就分配空间。

如果需要为某个case分支定义并初始化一个变量,我们应该把变量定义在块内,从而确保后面的所有case标签都在变量的作用域之外。

try语句块和异常处理

异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。

异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持:

  • throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发了异常。
  • try语句块,异常处理部分使用try语句块处理异常,try语句块以关键字try开始,并以一个或多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,所以它们也被称作异常处理代码。
  • 一套异常类,用于在throw表达式和相关的catch子句之间传递异常的具体信息。

throw表达式

程序的异常检测部分使用throw表达式引发一个异常。throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。throw表达式后通常紧跟一个分号,从而构成一条表达式语句。

throw runtime_error("Data must refer to same ISBN");

抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码。

try语句块

try语句块的通用语法形式是:

try {
program-statement
} catch (exception-declaration) {
handler-statements
} catch (exception-declaration) {
handler-statements;
} // ...

跟在try后的是一个或多个catch子句。catch子句包括三个部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明)以及一个块。当选中了某个catch子句处理异常后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。

try {
// ...
} catch (runtime_error err) {
cout << err.what() << endl;
// ...
}

每个标准库异常类都定义了名为what的成员函数,这些函数没有参数,返回值是C风格字符串。其中runtime_error的what成员返回的是初始化一个具体对象时所用的string对象的副本。

函数在寻找处理代码的过程中退出

在复杂系统中,程序在遇到抛出异常的代码前,其执行路径可能已经经过了多个try语句块。寻找处理代码的过程与函数调用链刚好相反,当异常被抛出时,首先搜索抛出该异常的函数。如果没找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。

如果最终还是没能找到任何匹配的catch子句,程序转到名为terminate的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。

标准异常

C++标准库定义了一组类,用于报告标准库函数遇到的问题,这些异常类也可以在用户编写的程序中使用。它们分别定义在4个头文件中:

  • exception头文件定义了最通用的异常类exception。它只报告异常的发生,不提供任何额外信息。
  • stdexcept头文件定义了几种常用的异常类。图片中列出。
  • new头文件定义了bad_alloc异常类型。
  • type_info头文件定义了bad_cast异常类型。

标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。

只能以默认初始化的方式初始化exception、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。其他异常类型的行为相反,应该使用string对象或者C风格字符串初始化这些类型的对象,但是不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,该初始值含有错误相关的信息。

异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char *。该字符串的目的是提供关于异常的一些文本信息。

what函数返回的C风格字符串的内容与异常对象的类型有关。如果异常类型有一个字符串初始值,则what返回该字符串。对于其他无初始值的异常类型来说,what返回的内容由编译器决定。

posted @   Pannnn  阅读(126)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
-->
点击右上角即可分享
微信分享提示