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 a
和double 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;
}
在这个示例中,复合语句(块)包含声明和表达式,块内的变量在块结束时作用域也结束。
重点与难点分析
重点:
- 简单语句的种类和用法:理解表达式语句、声明语句和空语句的作用和用法。
- 复合语句的结构和作用:掌握复合语句的语法和应用场景,理解其在控制结构中的重要性。
难点:
- 空语句的正确使用:初学者需要理解空语句的用途,避免在不适当的地方使用空语句。
- 复合语句中的作用域管理:掌握复合语句中变量的作用域,避免作用域混淆导致的错误。
练习题解析
- 练习5.1:编写一个包含多种简单语句的程序,输出结果。
- 示例代码
#include <iostream>
int main() {
int x = 5; // 声明语句
x = x + 2; // 表达式语句
; // 空语句
std::cout << "x: " << x << std::endl; // 函数调用语句
return 0;
}
- 练习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;
}
总结与提高
本节总结:
- 学习了简单语句的种类,包括表达式语句、声明语句和空语句,理解了它们在程序中的作用。
- 掌握了复合语句的结构和应用,理解了复合语句中变量的作用域。
- 理解了简单语句和复合语句的基本概念和用法,通过示例代码加深了对这些概念的理解。
提高建议:
- 多练习简单语句的使用:通过编写各种包含不同简单语句的程序,熟悉它们的用法和作用。
- 深入理解复合语句中的作用域管理:通过实践掌握复合语句中变量作用域的管理,避免作用域混淆导致的错误。
- 优化代码结构:在编写代码时,合理使用复合语句组织代码,提高代码的可读性和维护性。
5.2 语句作用域
5.2.1 基本概念
在C++中,作用域(scope)定义了标识符(如变量、函数、类型等)在程序中可见和可访问的区域。理解作用域的概念有助于避免命名冲突和不必要的错误,提高代码的可读性和可维护性。
5.2.2 作用域类型
C++中主要有以下几种作用域:
- 全局作用域:在整个程序中都可见和可访问的标识符。
- 局部作用域:在函数或复合语句(块)内定义的标识符,仅在定义它们的块内可见。
- 类作用域:在类或结构体内定义的标识符,仅在该类或结构体的成员函数内可见。
- 命名空间作用域:在命名空间内定义的标识符,仅在该命名空间内可见。
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_var
在main
函数和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;
}
在这个示例中,var
和display
函数在命名空间MyNamespace
内定义,只在该命名空间内可见。
重点与难点分析
重点:
- 作用域的基本概念:理解作用域的定义和作用,掌握不同类型的作用域及其应用场景。
- 局部和全局作用域:掌握局部和全局作用域的区别和使用方法,避免命名冲突和作用域混淆。
- 类作用域和命名空间作用域:理解类作用域和命名空间作用域的概念及其在实际编程中的应用。
难点:
- 作用域管理:初学者需要通过实践理解作用域的管理,避免变量作用域混淆导致的错误。
- 命名空间的使用:掌握命名空间的定义和使用,特别是在大型项目中的应用,避免命名冲突。
练习题解析
- 练习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;
}
- 练习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;
}
- 练习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;
}
总结与提高
本节总结:
- 学习了作用域的基本概念,理解了作用域在程序中的作用。
- 掌握了全局作用域、局部作用域、类作用域和命名空间作用域的定义和使用方法。
- 理解了不同作用域的应用场景,通过示例代码加深了对这些概念的理解。
提高建议:
- 多练习不同作用域的使用:通过编写各种包含不同作用域的程序,熟悉它们的用法和作用。
- 深入理解作用域管理:通过实践掌握作用域的管理,避免变量作用域混淆导致的错误。
- 优化代码结构:在编写代码时,合理使用作用域管理变量和函数,提高代码的可读性和维护性,特别是在大型项目中使用命名空间避免命名冲突。
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
语句中,用于同时检查两个变量的值。
重点与难点分析
重点:
- if语句的基本用法:掌握
if
语句的语法和用法,包括else if
和else
分支的使用。 - switch语句的基本用法:理解
switch
语句的语法和用法,掌握case
标签和default
标签的使用。 - 嵌套条件语句:理解条件语句的嵌套用法,能够编写多层次的条件判断结构。
难点:
- 条件语句的逻辑设计:初学者需要通过实践掌握条件语句的逻辑设计,确保条件判断的完整性和正确性。
- 避免代码重复和冗余:在使用条件语句时,应避免代码的重复和冗余,提高代码的可读性和维护性。
练习题解析
- 练习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;
}
- 练习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;
}
- 练习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;
}
总结与提高
本节总结:
- 学习了条件语句的基本概念,掌握了
if
语句和switch
语句的语法和用法。 - 理解了嵌套条件语句的结构和应用,能够编写多层次的条件判断结构。
- 通过示例代码和练习题,加深了对条件语句的理解和应用。
提高建议:
- 多练习条件语句的使用:通过编写各种包含条件语句的程序,熟悉
if
语句和switch
语句的用法。 - 深入理解条件语句的逻辑设计:通过实践掌握条件语句的逻辑设计,确保条件判断的完整性和正确性。
- 优化条件语句的结构:在编写条件语句时,避免代码的重复和冗余,提高代码的可读性和维护性。
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
中的每个元素,并输出其值。
重点与难点分析
重点:
- while循环和do while循环:掌握
while
循环和do while
循环的基本语法和用法,理解它们的区别。 - for循环:理解
for
循环的基本语法,掌握初始化语句、条件表达式和迭代语句的作用。 - 范围for语句:掌握范围
for
语句的用法,理解其在遍历容器中的优势。
难点:
- 循环控制:初学者需要通过实践掌握循环控制,包括循环的初始化、条件判断和迭代更新。
- 范围for语句的应用:熟悉范围
for
语句的语法和应用场景,特别是在处理标准库容器时的应用。
练习题解析
- 练习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;
}
- 练习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;
}
- 练习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;
}
- 练习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;
}
总结与提高
本节总结:
- 学习了迭代语句的基本概念,掌握了
while
循环、do while
循环和for
循环的语法和用法。 - 理解了范围
for
语句的结构和应用,能够使用范围for
语句遍历数组和标准库容器。 - 通过示例代码和练习题,加深了对迭代语句的理解和应用。
提高建议:
- 多练习迭代语句的使用:通过编写各种包含迭代语句的程序,熟悉
while
循环、do while
循环、for
循环和范围for
语句的用法。 - 深入理解循环控制:通过实践掌握循环的初始化、条件判断和迭代更新,确保循环的正确执行。
- 优化循环的效率:在编写循环时,注意循环的效率和性能,避免不必要的计算和重复操作,提高代码的执行效率。
5.5 跳转语句
5.5.1 基本概念
跳转语句用于在程序中改变控制流,直接跳转到程序的另一个部分。C++中的主要跳转语句包括break
、continue
、goto
、return
和异常处理相关的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
块中捕获和处理。
重点与难点分析
重点:
- break和continue语句:掌握
break
和continue
语句的基本用法,理解它们在循环中的作用。 - goto语句:了解
goto
语句的用法和潜在问题,避免滥用。 - return语句:理解
return
语句的基本用法,掌握其在函数中的作用。 - throw语句:初步了解
throw
语句的用法,理解其在异常处理中的作用。
难点:
- 跳转控制:初学者需要通过实践掌握不同跳转语句的控制流,理解它们在程序中的具体应用场景。
- 异常处理:虽然
throw
语句在本章只是简单介绍,但理解其在异常处理中的作用是一个难点,需要在后续章节中深入学习。
练习题解析
- 练习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;
}
- 练习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;
}
- 练习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;
}
- 练习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;
}
- 练习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;
}
总结与提高
本节总结:
- 学习了跳转语句的基本概念,掌握了
break
、continue
、goto
、return
和throw
语句的用法。 - 理解了跳转语句在控制程序流中的作用,并通过示例代码加深了对这些概念的理解。
- 初步了解了异常处理中的
throw
语句,理解其在异常处理中的作用。
提高建议:
- 多练习跳转语句的使用:通过编写各种包含跳转语句的程序,熟悉
break
、continue
、goto
、return
和throw
语句的用法。 - 深入理解跳转控制:通过实践掌握跳转语句的控制流,理解它们在程序中的具体应用场景。
- 避免滥用goto语句:在编写代码时,应尽量避免使用
goto
语句,以提高代码的可读性和维护性。 - 学习异常处理:后续章节中将深入学习异常处理,掌握
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
函数中捕获和处理该异常。
重点与难点分析
重点
- 异常处理的基本概念:理解
try
、throw
和catch
语句的基本概念和用法。 - 标准异常类的使用:掌握常见的标准异常类及其应用场景。
难点
- 异常的传播和捕获:初学者需要通过实践理解异常的传播机制及如何正确捕获和处理异常。
- 自定义异常类:在复杂项目中,自定义异常类可以提高代码的可读性和可维护性,需要掌握自定义异常类的方法。
练习题解析
- 练习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;
}
- 练习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;
}
- 练习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;
}
总结与提高
本节总结
- 学习了异常处理的基本概念,掌握了
try
、throw
和catch
语句的用法。 - 理解了标准异常类的应用场景,并通过示例代码加深了对这些概念的理解。
- 掌握了异常的传播机制及其在程序中的具体应用。
提高建议
- 多练习异常处理的使用:通过编写各种包含异常处理的程序,熟悉
try
、throw
和catch
语句的用法。 - 深入理解异常的传播和捕获:通过实践掌握异常的传播机制及其在程序中的具体应用,确保异常能够被正确捕获和处理。
- 自定义异常类:在复杂项目中,自定义异常类可以提高代码的可读性和可维护性,掌握自定义异常类的方法。
标签:语句,std,示例,int,代码,C++,导学,作用域,Primer From: https://blog.csdn.net/iShare_Carlos/article/details/139769415本主页会定期更新,为了能够及时获得更新,敬请关注我:点击左下角的关注。也可以关注公众号:请在微信上搜索公众号“iShare爱分享”并关注,或者扫描以下公众号二维码关注,以便在内容更新时直接向您推送。