assert函数和捕获异常
assert函数
-
C语言和C++都有一个专门为调试而准备的工具函数,就是assert函数。
-
assert函数只有一个参数,相当于if语句的使用
assert( 判断语句 ); 如果为真,就什么都不做; 如果为假,程序中断,并给出提示
include<cassert>
int main()
{
int i=20;
assert(i==50);
return 0;
}
- 以上,我们可以知道assert函数可以帮助我们调试程序,我们可以利用它在某个程序里的关键假设不成立时,立刻停止该程序的运行并报错。
捕获异常
使用基本思路
- 安排一些C++代码(try语句)去尝试某件事—尤其是那些可能会失败的事情(比如,打开一个文件或申请一些内存)
- 如果发生问题,就抛出一个异常(throw语句)
- 再安排一些代码(catch语句)去捕获这个异常并进行相应的处理
基本语法
try
{
//do something
//Throw an expection on error
}
catch
{
//do Whatever
}
注意:
- 每条try语句必须有一条对应的catch语句。
- catch语句必须定义,以便接受一个特定类型的参数。
- 我们还可以定义多条case语句,来对应多种可能的异常类型。
当在try语句块内时,一旦执行throw语句,这个块内后面的其他语句就不会被执行,程序被挂起。
由此我们可以知道,和return语句相比,采用异常处理机制的好处是他可以把程序正常功能和逻辑出错时的处理部分清晰地划分开。
如何让函数抛出异常
-
在函数声明的后面加上 throw (type); 表明你希望它可以抛出的异常的类型。
type functionName(arguments) throw (type);
-
C++17标准把throw语句改为noexcept(false)语句
理解
- try语句里存放不确定会发生什么的代码
- catch语句里,存放如果出现问题,那么去执行的代码
- 抛出异常和catch语句的作用就是把程序从发生问题的代码引到处理错误的代码那里。
- 一般对抛出异常和catch的参数是定义为字符串指针,直接打印相关的错误信息。
TIPS
- 使用原则:应该只用他们来处理,确实可能存在不正常的情况。
- 在构造器和析构器里面,不要使用异常。
- 如果打算使用对象作为异常,那么:以“值传递”方式抛出对象,以“引用传递”的方式捕获对象。
代码实现
#include <iostream>
#include <climits>
using namespace std;
unsigned long returnFactorial(unsigned short num) throw(const char*);
int main()
{
unsigned short num = 0;
cout << "请输入一个整数:";
while( !(cin>>num) || (num < 1) )
{
cin.clear();//清楚状态
cin.ignore(100,'\n'); //清除缓存区
cout << "请输入一个整数:";
}
cin.ignore(100,'\n');
try
{
unsigned long factorial = returnFactorial(num);//如果异常,则抛出字符型的*e异常
//直接跳转到catch继续执行
cout << num << "的阶乘值是:" << factorial;
}
catch(const char *e)//如果正常则不执行,抛出异常则执行
{
cout << "error";
}
return 0;
}
unsigned long returnFactorial(unsigned short num) throw(const char*)
{
unsigned long sum = 1;
unsigned long max = ULONG_MAX;
for(int i = 1;i <= num; i++)
{
sum *= i;
max /= i;
}
if(max < 1)
{
throw"悲催。。。该基数太大,无法在该计算机计算求出阶乘值。\n";
}
else
{
return sum;
}
}