《C++ Primer》导学系列:第 5 章 - 语句

2024-06-18 14:04
文章标签 c++ 系列 语句 导学 primer

本文主要是介绍《C++ Primer》导学系列:第 5 章 - 语句,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

5.1 简单语句

5.1.1 基本概念

在C++中,简单语句是构成程序的基本单元。每个简单语句以分号(;)结束,可以是表达式、声明或空语句。

5.1.2 表达式语句

表达式语句是由表达式构成的语句,通常用于计算、赋值和函数调用。

示例代码
#include <iostream>int main() {int a = 10;  // 赋值表达式语句a = a + 1;  // 计算并赋值std::cout << "a: " << a << std::endl;  // 函数调用语句return 0;
}

在这个示例中,每行代码都是一个表达式语句,执行赋值、计算和输出操作。

5.1.3 声明语句

声明语句用于声明变量、函数或类型,告诉编译器它们的存在和类型信息。

示例代码
#include <iostream>int main() {int a = 10;  // 声明并初始化变量double b = 3.14;  // 声明并初始化变量std::cout << "a: " << a << ", b: " << b << std::endl;return 0;
}

在这个示例中,int adouble b是声明语句,它们声明并初始化了变量。

5.1.4 空语句

空语句仅由一个分号构成,不执行任何操作。通常用于需要语法上要求一个语句但实际不需要做任何事情的地方。

示例代码
#include <iostream>int main() {int a = 0;while (a < 10) {;  // 空语句,循环体不执行任何操作++a;}std::cout << "a: " << a << std::endl;  // 输出 a 的值return 0;
}

在这个示例中,空语句用于while循环体,但没有实际操作。

5.1.5 复合语句(块)

复合语句由一对花括号{}包围的一系列语句组成,通常用于控制语句和函数体中。复合语句可以包含声明和其他语句,是形成控制结构的基础。

示例代码
#include <iostream>int main() {int a = 0;{int b = 10;  // 复合语句中的声明a = a + b;  // 复合语句中的表达式std::cout << "Inside block: a: " << a << std::endl;}  // 复合语句的结束,b 的作用域结束std::cout << "Outside block: a: " << a << std::endl;return 0;
}

在这个示例中,复合语句(块)包含声明和表达式,块内的变量在块结束时作用域也结束。

重点与难点分析

重点

  1. 简单语句的种类和用法:理解表达式语句、声明语句和空语句的作用和用法。
  2. 复合语句的结构和作用:掌握复合语句的语法和应用场景,理解其在控制结构中的重要性。

难点

  1. 空语句的正确使用:初学者需要理解空语句的用途,避免在不适当的地方使用空语句。
  2. 复合语句中的作用域管理:掌握复合语句中变量的作用域,避免作用域混淆导致的错误。

练习题解析

  1. 练习5.1:编写一个包含多种简单语句的程序,输出结果。
  • 示例代码
#include <iostream>int main() {int x = 5;  // 声明语句x = x + 2;  // 表达式语句;  // 空语句std::cout << "x: " << x << std::endl;  // 函数调用语句return 0;
}

  1. 练习5.2:编写一个包含复合语句的程序,演示变量的作用域。
  • 示例代码
#include <iostream>int main() {int a = 10;{int b = 20;a = a + b;std::cout << "Inside block: a: " << a << ", b: " << b << std::endl;}// b 的作用域结束,下面的代码会引发错误// std::cout << "Outside block: b: " << b << std::endl;  std::cout << "Outside block: a: " << a << std::endl;return 0;
}

总结与提高

本节总结

  1. 学习了简单语句的种类,包括表达式语句、声明语句和空语句,理解了它们在程序中的作用。
  2. 掌握了复合语句的结构和应用,理解了复合语句中变量的作用域。
  3. 理解了简单语句和复合语句的基本概念和用法,通过示例代码加深了对这些概念的理解。

提高建议

  1. 多练习简单语句的使用:通过编写各种包含不同简单语句的程序,熟悉它们的用法和作用。
  2. 深入理解复合语句中的作用域管理:通过实践掌握复合语句中变量作用域的管理,避免作用域混淆导致的错误。
  3. 优化代码结构:在编写代码时,合理使用复合语句组织代码,提高代码的可读性和维护性。

5.2 语句作用域

5.2.1 基本概念

在C++中,作用域(scope)定义了标识符(如变量、函数、类型等)在程序中可见和可访问的区域。理解作用域的概念有助于避免命名冲突和不必要的错误,提高代码的可读性和可维护性。

5.2.2 作用域类型

C++中主要有以下几种作用域:

  1. 全局作用域:在整个程序中都可见和可访问的标识符。
  2. 局部作用域:在函数或复合语句(块)内定义的标识符,仅在定义它们的块内可见。
  3. 类作用域:在类或结构体内定义的标识符,仅在该类或结构体的成员函数内可见。
  4. 命名空间作用域:在命名空间内定义的标识符,仅在该命名空间内可见。

5.2.3 全局作用域

全局作用域中的标识符在整个程序中都可见,通常在文件的最外层定义。

示例代码
#include <iostream>int global_var = 100;  // 全局作用域变量void func() {std::cout << "Global variable: " << global_var << std::endl;
}int main() {std::cout << "Global variable in main: " << global_var << std::endl;func();return 0;
}

在这个示例中,global_var是一个全局作用域变量,在main函数和func函数中都可见和可访问。

5.2.4 局部作用域

局部作用域中的标识符在其定义的函数或块内可见,离开该块后不可见。

示例代码
#include <iostream>void func() {int local_var = 10;  // 局部作用域变量std::cout << "Local variable in func: " << local_var << std::endl;
}int main() {int local_var = 20;  // 局部作用域变量std::cout << "Local variable in main: " << local_var << std::endl;func();return 0;
}

在这个示例中,local_varmain函数和func函数中分别定义,并且只在各自的函数内可见。

5.2.5 类作用域

类作用域中的标识符在类或结构体的成员函数内可见。

示例代码
#include <iostream>class MyClass {
public:MyClass(int val) : member_var(val) {}void display() {std::cout << "Member variable: " << member_var << std::endl;}
private:int member_var;  // 类作用域变量
};int main() {MyClass obj(42);obj.display();return 0;
}

在这个示例中,member_var是类MyClass的成员变量,仅在类的成员函数display内可见。

5.2.6 命名空间作用域

命名空间作用域中的标识符在定义它们的命名空间内可见,可以避免全局命名冲突。

示例代码
#include <iostream>namespace MyNamespace {int var = 50;  // 命名空间作用域变量void display() {std::cout << "Namespace variable: " << var << std::endl;}
}int main() {MyNamespace::display();std::cout << "Namespace variable in main: " << MyNamespace::var << std::endl;return 0;
}

在这个示例中,vardisplay函数在命名空间MyNamespace内定义,只在该命名空间内可见。

重点与难点分析

重点:

  1. 作用域的基本概念:理解作用域的定义和作用,掌握不同类型的作用域及其应用场景。
  2. 局部和全局作用域:掌握局部和全局作用域的区别和使用方法,避免命名冲突和作用域混淆。
  3. 类作用域和命名空间作用域:理解类作用域和命名空间作用域的概念及其在实际编程中的应用。

难点

  1. 作用域管理:初学者需要通过实践理解作用域的管理,避免变量作用域混淆导致的错误。
  2. 命名空间的使用:掌握命名空间的定义和使用,特别是在大型项目中的应用,避免命名冲突。

练习题解析

  1. 练习5.3:编写一个包含全局变量和局部变量的程序,输出它们的值。
  • 示例代码
#include <iostream>int global_var = 100;  // 全局变量void func() {int local_var = 10;  // 局部变量std::cout << "Local variable in func: " << local_var << std::endl;std::cout << "Global variable in func: " << global_var << std::endl;
}int main() {int local_var = 20;  // 局部变量std::cout << "Local variable in main: " << local_var << std::endl;std::cout << "Global variable in main: " << global_var << std::endl;func();return 0;
}

  1. 练习5.4:编写一个包含类作用域变量的程序,并在类的成员函数中输出其值。
  • 示例代码
#include <iostream>class MyClass {
public:MyClass(int val) : member_var(val) {}void display() {std::cout << "Member variable: " << member_var << std::endl;}
private:int member_var;  // 类作用域变量
};int main() {MyClass obj(42);obj.display();return 0;
}

  1. 练习5.5:编写一个使用命名空间的程序,定义命名空间变量并在命名空间内的函数中输出其值。
  • 示例代码
#include <iostream>namespace MyNamespace {int var = 50;  // 命名空间变量void display() {std::cout << "Namespace variable: " << var << std::endl;}
}int main() {MyNamespace::display();std::cout << "Namespace variable in main: " << MyNamespace::var << std::endl;return 0;
}

总结与提高

本节总结

  1. 学习了作用域的基本概念,理解了作用域在程序中的作用。
  2. 掌握了全局作用域、局部作用域、类作用域和命名空间作用域的定义和使用方法。
  3. 理解了不同作用域的应用场景,通过示例代码加深了对这些概念的理解。

提高建议

  1. 多练习不同作用域的使用:通过编写各种包含不同作用域的程序,熟悉它们的用法和作用。
  2. 深入理解作用域管理:通过实践掌握作用域的管理,避免变量作用域混淆导致的错误。
  3. 优化代码结构:在编写代码时,合理使用作用域管理变量和函数,提高代码的可读性和维护性,特别是在大型项目中使用命名空间避免命名冲突。

5.3 条件语句

5.3.1 基本概念

条件语句用于根据表达式的值来控制程序的执行流程。C++中的条件语句主要包括if语句和switch语句。

5.3.2 if语句

if语句根据一个条件表达式的布尔值决定是否执行一个代码块。if语句可以有一个可选的else分支和多个else if分支。

基本语法
if (condition) {// 当 condition 为 true 时执行的代码
} else if (another_condition) {// 当 another_condition 为 true 时执行的代码
} else {// 当所有条件都不满足时执行的代码
}

示例代码
#include <iostream>int main() {int a = 10;if (a > 0) {std::cout << "a is positive" << std::endl;} else if (a == 0) {std::cout << "a is zero" << std::endl;} else {std::cout << "a is negative" << std::endl;}return 0;
}

在这个示例中,if语句检查a的值,并根据不同的条件执行不同的代码块。

5.3.3 switch语句

switch语句根据一个整数表达式的值选择要执行的代码块。每个代码块由一个或多个case标签标识,switch语句还可以包含一个可选的default标签。

基本语法
switch (expression) {case constant1:// 当 expression 等于 constant1 时执行的代码break;case constant2:// 当 expression 等于 constant2 时执行的代码break;default:// 当所有 case 都不匹配时执行的代码
}

示例代码
#include <iostream>int main() {int a = 2;switch (a) {case 1:std::cout << "a is 1" << std::endl;break;case 2:std::cout << "a is 2" << std::endl;break;case 3:std::cout << "a is 3" << std::endl;break;default:std::cout << "a is not 1, 2, or 3" << std::endl;}return 0;
}

在这个示例中,switch语句检查a的值,并根据匹配的case标签执行相应的代码块。

5.3.4 嵌套条件语句

条件语句可以嵌套使用,即在一个条件语句的代码块中包含另一个条件语句。这种嵌套结构可以处理更复杂的条件判断。

示例代码
#include <iostream>int main() {int a = 10;int b = 20;if (a > 0) {if (b > 0) {std::cout << "a and b are positive" << std::endl;} else {std::cout << "a is positive but b is not" << std::endl;}} else {std::cout << "a is not positive" << std::endl;}return 0;
}

在这个示例中,if语句嵌套在另一个if语句中,用于同时检查两个变量的值。

重点与难点分析

重点

  1. if语句的基本用法:掌握if语句的语法和用法,包括else ifelse分支的使用。
  2. switch语句的基本用法:理解switch语句的语法和用法,掌握case标签和default标签的使用。
  3. 嵌套条件语句:理解条件语句的嵌套用法,能够编写多层次的条件判断结构。

难点

  1. 条件语句的逻辑设计:初学者需要通过实践掌握条件语句的逻辑设计,确保条件判断的完整性和正确性。
  2. 避免代码重复和冗余:在使用条件语句时,应避免代码的重复和冗余,提高代码的可读性和维护性。

练习题解析

  1. 练习5.6:编写一个包含if-else语句的程序,根据用户输入的分数判断并输出相应的等级。
  • 示例代码
#include <iostream>int main() {int score;std::cout << "Enter your score: ";std::cin >> score;if (score >= 90) {std::cout << "Grade: A" << std::endl;} else if (score >= 80) {std::cout << "Grade: B" << std::endl;} else if (score >= 70) {std::cout << "Grade: C" << std::endl;} else if (score >= 60) {std::cout << "Grade: D" << std::endl;} else {std::cout << "Grade: F" << std::endl;}return 0;
}

  1. 练习5.7:编写一个包含switch语句的程序,根据用户输入的月份输出相应的季节。
  • 示例代码
#include <iostream>int main() {int month;std::cout << "Enter the month (1-12): ";std::cin >> month;switch (month) {case 12:case 1:case 2:std::cout << "Winter" << std::endl;break;case 3:case 4:case 5:std::cout << "Spring" << std::endl;break;case 6:case 7:case 8:std::cout << "Summer" << std::endl;break;case 9:case 10:case 11:std::cout << "Fall" << std::endl;break;default:std::cout << "Invalid month" << std::endl;}return 0;
}

  1. 练习5.8:编写一个嵌套if语句的程序,根据用户输入的年龄判断并输出相应的票价。
  • 示例代码
#include <iostream>int main() {int age;std::cout << "Enter your age: ";std::cin >> age;if (age < 12) {std::cout << "Ticket price: $5" << std::endl;} else {if (age < 60) {std::cout << "Ticket price: $10" << std::endl;} else {std::cout << "Ticket price: $7" << std::endl;}}return 0;
}

总结与提高

本节总结

  1. 学习了条件语句的基本概念,掌握了if语句和switch语句的语法和用法。
  2. 理解了嵌套条件语句的结构和应用,能够编写多层次的条件判断结构。
  3. 通过示例代码和练习题,加深了对条件语句的理解和应用。

提高建议

  1. 多练习条件语句的使用:通过编写各种包含条件语句的程序,熟悉if语句和switch语句的用法。
  2. 深入理解条件语句的逻辑设计:通过实践掌握条件语句的逻辑设计,确保条件判断的完整性和正确性。
  3. 优化条件语句的结构:在编写条件语句时,避免代码的重复和冗余,提高代码的可读性和维护性。

5.4 迭代语句

5.4.1 基本概念

迭代语句,也称为循环语句,用于反复执行某段代码,直到满足特定条件为止。C++提供了三种主要的迭代语句:while循环、do while循环和for循环。

5.4.2 while循环

while循环在每次迭代之前测试条件表达式,如果条件为真,则执行循环体;如果条件为假,则退出循环。

基本语法
while (condition) {// 循环体
}

示例代码
#include <iostream>int main() {int i = 0;while (i < 5) {std::cout << "i: " << i << std::endl;++i;}return 0;
}

在这个示例中,while循环打印变量i的值,直到i不再小于5。

5.4.3 do while循环

do while循环与while循环类似,但不同的是,do while循环在每次迭代之后测试条件表达式。这意味着do while循环至少执行一次。

基本语法
do {// 循环体
} while (condition);

示例代码
#include <iostream>int main() {int i = 0;do {std::cout << "i: " << i << std::endl;++i;} while (i < 5);return 0;
}

在这个示例中,do while循环确保循环体至少执行一次,即使初始条件为假。

5.4.4 for循环

for循环通常用于需要明确控制循环变量的迭代次数的情况。for循环包含初始化语句、条件表达式和迭代语句。

基本语法
for (initialization; condition; iteration) {// 循环体
}

示例代码
#include <iostream>int main() {for (int i = 0; i < 5; ++i) {std::cout << "i: " << i << std::endl;}return 0;
}

在这个示例中,for循环打印变量i的值,从0到4。

5.4.5 范围for语句

C++11引入了范围for语句(range-based for loop),用于遍历数组或其他容器。范围for语句使代码更加简洁和可读。

基本语法
for (declaration : expression) {// 循环体
}
  • declaration是用于引用容器元素的变量声明。
  • expression是一个可迭代的容器或范围。

示例代码
#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};for (int value : vec) {std::cout << "value: " << value << std::endl;}return 0;
}

在这个示例中,范围for循环遍历vec中的每个元素,并输出其值。

重点与难点分析

重点

  1. while循环和do while循环:掌握while循环和do while循环的基本语法和用法,理解它们的区别。
  2. for循环:理解for循环的基本语法,掌握初始化语句、条件表达式和迭代语句的作用。
  3. 范围for语句:掌握范围for语句的用法,理解其在遍历容器中的优势。

难点

  1. 循环控制:初学者需要通过实践掌握循环控制,包括循环的初始化、条件判断和迭代更新。
  2. 范围for语句的应用:熟悉范围for语句的语法和应用场景,特别是在处理标准库容器时的应用。

练习题解析

  1. 练习5.9:编写一个while循环,计算并输出1到10的和。
  • 示例代码
#include <iostream>int main() {int sum = 0;int i = 1;while (i <= 10) {sum += i;++i;}std::cout << "Sum: " << sum << std::endl;return 0;
}

  1. 练习5.10:编写一个do while循环,反复读取用户输入,直到输入0为止。
  • 示例代码
#include <iostream>int main() {int number;do {std::cout << "Enter a number (0 to exit): ";std::cin >> number;} while (number != 0);std::cout << "Goodbye!" << std::endl;return 0;
}

  1. 练习5.11:编写一个for循环,输出1到10的平方。
  • 示例代码
#include <iostream>int main() {for (int i = 1; i <= 10; ++i) {std::cout << "Square of " << i << " is " << i * i << std::endl;}return 0;
}

  1. 练习5.12:编写一个使用范围for语句的程序,输出数组中的每个元素。
  • 示例代码
#include <iostream>int main() {int arr[] = {1, 2, 3, 4, 5};for (int value : arr) {std::cout << "value: " << value << std::endl;}return 0;
}

总结与提高

本节总结

  1. 学习了迭代语句的基本概念,掌握了while循环、do while循环和for循环的语法和用法。
  2. 理解了范围for语句的结构和应用,能够使用范围for语句遍历数组和标准库容器。
  3. 通过示例代码和练习题,加深了对迭代语句的理解和应用。

提高建议

  1. 多练习迭代语句的使用:通过编写各种包含迭代语句的程序,熟悉while循环、do while循环、for循环和范围for语句的用法。
  2. 深入理解循环控制:通过实践掌握循环的初始化、条件判断和迭代更新,确保循环的正确执行。
  3. 优化循环的效率:在编写循环时,注意循环的效率和性能,避免不必要的计算和重复操作,提高代码的执行效率。

5.5 跳转语句

5.5.1 基本概念

跳转语句用于在程序中改变控制流,直接跳转到程序的另一个部分。C++中的主要跳转语句包括breakcontinuegotoreturn和异常处理相关的throw

5.5.2 break语句

break语句用于立即终止所在的循环或switch语句,并跳转到紧接着循环或switch语句后的语句。

示例代码
#include <iostream>int main() {for (int i = 0; i < 10; ++i) {if (i == 5) {break;  // 当 i 等于 5 时,跳出循环}std::cout << "i: " << i << std::endl;}std::cout << "Loop ended." << std::endl;return 0;
}

在这个示例中,当i等于5时,break语句终止for循环。

5.5.3 continue语句

continue语句用于跳过当前循环迭代的剩余部分,并继续执行下一次循环迭代。

示例代码
#include <iostream>int main() {for (int i = 0; i < 10; ++i) {if (i % 2 == 0) {continue;  // 跳过偶数}std::cout << "i: " << i << std::endl;}return 0;
}

在这个示例中,continue语句跳过偶数的输出,只输出奇数。

5.5.4 goto语句

goto语句用于无条件跳转到程序中的指定标签。尽管goto语句很强大,但滥用会导致代码难以阅读和维护,因此通常应避免使用。

示例代码
#include <iostream>int main() {int i = 0;start:std::cout << "i: " << i << std::endl;++i;if (i < 5) {goto start;  // 跳转到标签 start}return 0;
}

在这个示例中,goto语句跳转到标签start,实现了一个简单的循环。

5.5.5 return语句

return语句用于终止函数的执行,并将控制权返回给调用函数。return语句可以带有一个返回值,该值将作为函数调用的结果。

示例代码
#include <iostream>int add(int a, int b) {return a + b;  // 返回两个整数的和
}int main() {int result = add(5, 3);std::cout << "Result: " << result << std::endl;return 0;
}

在这个示例中,return语句将add函数的结果返回给调用者。

5.5.6 throw语句

throw语句用于抛出一个异常,使程序跳转到最近的异常处理器。异常处理在第18章详细讨论,这里只作简单介绍。

示例代码
#include <iostream>
#include <stdexcept>int main() {try {throw std::runtime_error("An error occurred");  // 抛出异常} catch (const std::runtime_error& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

在这个示例中,throw语句抛出一个std::runtime_error异常,并在catch块中捕获和处理。

重点与难点分析

重点

  1. break和continue语句:掌握breakcontinue语句的基本用法,理解它们在循环中的作用。
  2. goto语句:了解goto语句的用法和潜在问题,避免滥用。
  3. return语句:理解return语句的基本用法,掌握其在函数中的作用。
  4. throw语句:初步了解throw语句的用法,理解其在异常处理中的作用。

难点

  1. 跳转控制:初学者需要通过实践掌握不同跳转语句的控制流,理解它们在程序中的具体应用场景。
  2. 异常处理:虽然throw语句在本章只是简单介绍,但理解其在异常处理中的作用是一个难点,需要在后续章节中深入学习。

练习题解析

  1. 练习5.13:编写一个程序,使用break语句终止循环。
  • 示例代码
#include <iostream>int main() {for (int i = 0; i < 10; ++i) {if (i == 7) {break;  // 当 i 等于 7 时,跳出循环}std::cout << "i: " << i << std::endl;}std::cout << "Loop ended." << std::endl;return 0;
}

  1. 练习5.14:编写一个程序,使用continue语句跳过循环中的某些迭代。
  • 示例代码
#include <iostream>int main() {for (int i = 0; i < 10; ++i) {if (i % 3 == 0) {continue;  // 跳过能被 3 整除的数字}std::cout << "i: " << i << std::endl;}return 0;
}

  1. 练习5.15:编写一个程序,使用goto语句实现循环,并注意避免滥用。
  • 示例代码
#include <iostream>int main() {int i = 0;start:std::cout << "i: " << i << std::endl;++i;if (i < 5) {goto start;  // 跳转到标签 start}return 0;
}

  1. 练习5.16:编写一个包含return语句的函数,并调用该函数输出其返回值。
  • 示例代码
#include <iostream>int multiply(int a, int b) {return a * b;  // 返回两个整数的乘积
}int main() {int result = multiply(4, 5);std::cout << "Result: " << result << std::endl;return 0;
}

  1. 练习5.17:编写一个程序,使用throw语句抛出一个异常,并在catch块中处理该异常。
  • 示例代码
#include <iostream>
#include <stdexcept>int main() {try {throw std::runtime_error("An error occurred");  // 抛出异常} catch (const std::runtime_error& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

总结与提高

本节总结

  1. 学习了跳转语句的基本概念,掌握了breakcontinuegotoreturnthrow语句的用法。
  2. 理解了跳转语句在控制程序流中的作用,并通过示例代码加深了对这些概念的理解。
  3. 初步了解了异常处理中的throw语句,理解其在异常处理中的作用。

提高建议

  1. 多练习跳转语句的使用:通过编写各种包含跳转语句的程序,熟悉breakcontinuegotoreturnthrow语句的用法。
  2. 深入理解跳转控制:通过实践掌握跳转语句的控制流,理解它们在程序中的具体应用场景。
  3. 避免滥用goto语句:在编写代码时,应尽量避免使用goto语句,以提高代码的可读性和维护性。
  4. 学习异常处理:后续章节中将深入学习异常处理,掌握throw语句及其相关的异常处理机制。

5.6 try语句块和异常处理

5.6.1 基本概念

异常处理是C++中用于应对程序运行过程中出现的错误情况的一种机制。通过异常处理,可以将错误与正常的代码逻辑分开,使程序更加健壮和易于维护。异常处理的核心机制包括try语句块、throw语句和catch语句。

5.6.2 try语句块

try语句块用于包围可能引发异常的代码。当try语句块中的代码抛出异常时,程序控制流将转移到相应的catch块中。

基本语法
try {// 可能引发异常的代码
} catch (exceptionType1 e1) {// 处理 exceptionType1 类型的异常
} catch (exceptionType2 e2) {// 处理 exceptionType2 类型的异常
}

5.6.3 throw语句

throw语句用于抛出一个异常,使程序跳转到最近的匹配catch块。throw语句可以抛出任意类型的对象,但通常抛出派生自std::exception的异常对象。

基本语法
throw exceptionObject;

示例代码
#include <iostream>
#include <stdexcept>int divide(int a, int b) {if (b == 0) {throw std::runtime_error("Division by zero");  // 抛出异常}return a / b;
}int main() {try {int result = divide(10, 0);std::cout << "Result: " << result << std::endl;} catch (const std::runtime_error& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

在这个示例中,divide函数在除数为零时抛出std::runtime_error异常,并在main函数中捕获和处理该异常。

5.6.4 catch语句

catch语句用于捕获由try块抛出的异常,并执行处理代码。一个try块可以有多个catch块,每个catch块处理不同类型的异常。

基本语法
catch (exceptionType e) {// 处理异常的代码
}

示例代码
#include <iostream>
#include <stdexcept>int main() {try {throw std::runtime_error("An error occurred");} catch (const std::runtime_error& e) {std::cout << "Caught exception: " << e.what() << std::endl;} catch (const std::exception& e) {std::cout << "Caught general exception: " << e.what() << std::endl;}return 0;
}

在这个示例中,catch块捕获并处理std::runtime_error异常和其他std::exception类型的异常。

5.6.5 标准异常类

C++标准库提供了一些常用的异常类,这些类派生自std::exception。常见的标准异常类包括:

  • std::runtime_error
  • std::logic_error
  • std::out_of_range
  • std::invalid_argument
  • std::bad_alloc

示例代码
#include <iostream>
#include <stdexcept>void checkIndex(int index, int size) {if (index < 0 || index >= size) {throw std::out_of_range("Index out of range");}
}int main() {try {checkIndex(10, 5);} catch (const std::out_of_range& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

在这个示例中,checkIndex函数在索引超出范围时抛出std::out_of_range异常,并在main函数中捕获和处理该异常。

重点与难点分析

重点

  1. 异常处理的基本概念:理解trythrowcatch语句的基本概念和用法。
  2. 标准异常类的使用:掌握常见的标准异常类及其应用场景。

难点

  1. 异常的传播和捕获:初学者需要通过实践理解异常的传播机制及如何正确捕获和处理异常。
  2. 自定义异常类:在复杂项目中,自定义异常类可以提高代码的可读性和可维护性,需要掌握自定义异常类的方法。

练习题解析

  1. 练习5.18:编写一个函数,抛出一个标准异常,并在main函数中捕获并处理该异常。
  • 示例代码
#include <iostream>
#include <stdexcept>void func() {throw std::runtime_error("An error occurred in func");
}int main() {try {func();} catch (const std::runtime_error& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

  1. 练习5.19:编写一个包含多个catch块的程序,捕获不同类型的异常。
  • 示例代码
#include <iostream>
#include <stdexcept>int main() {try {throw std::out_of_range("Out of range error");} catch (const std::out_of_range& e) {std::cout << "Caught out_of_range exception: " << e.what() << std::endl;} catch (const std::exception& e) {std::cout << "Caught general exception: " << e.what() << std::endl;}return 0;
}

  1. 练习5.20:编写一个函数,使用throw语句抛出一个自定义异常类,并在main函数中捕获并处理该异常。
  • 示例代码
#include <iostream>
#include <stdexcept>class MyException : public std::exception {
public:const char* what() const noexcept override {return "My custom exception";}
};void func() {throw MyException();
}int main() {try {func();} catch (const MyException& e) {std::cout << "Caught MyException: " << e.what() << std::endl;} catch (const std::exception& e) {std::cout << "Caught general exception: " << e.what() << std::endl;}return 0;
}

总结与提高

本节总结

  1. 学习了异常处理的基本概念,掌握了trythrowcatch语句的用法。
  2. 理解了标准异常类的应用场景,并通过示例代码加深了对这些概念的理解。
  3. 掌握了异常的传播机制及其在程序中的具体应用。

提高建议

  1. 多练习异常处理的使用:通过编写各种包含异常处理的程序,熟悉trythrowcatch语句的用法。
  2. 深入理解异常的传播和捕获:通过实践掌握异常的传播机制及其在程序中的具体应用,确保异常能够被正确捕获和处理。
  3. 自定义异常类:在复杂项目中,自定义异常类可以提高代码的可读性和可维护性,掌握自定义异常类的方法。

本主页会定期更新,为了能够及时获得更新,敬请关注我:点击左下角的关注。也可以关注公众号:请在微信上搜索公众号“iShare爱分享”并关注,或者扫描以下公众号二维码关注,以便在内容更新时直接向您推送。 

这篇关于《C++ Primer》导学系列:第 5 章 - 语句的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1072194

相关文章

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在MySQL执行UPDATE语句时遇到的错误1175的解决方案

《在MySQL执行UPDATE语句时遇到的错误1175的解决方案》MySQL安全更新模式(SafeUpdateMode)限制了UPDATE和DELETE操作,要求使用WHERE子句时必须基于主键或索引... mysql 中遇到的 Error Code: 1175 是由于启用了 安全更新模式(Safe Upd

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、