类和结构的异常处理
C++异常处理的真正能力不仅在于它能处理各种不同类型的异常,还在于它具有在异常抛弃前为构造的所有局部对象自动调用析构函数的能力
异常处理中的构造和析构
当在程序中找到一个匹配的catch异常处理后,如果catch( )语句的异常类型声明是一个值参数,则其初始化方式是复制被抛弃的异常对象;如果catch( )语句的异常类型是一个引用,则其初始化方式是使该引用指向异常对象
当catch语句的异常类型参数被初始化后,便开始了栈的展开过程,包括从对应的try语句块开始到异常被抛弃之间,对构造的所有自动对象进行析构。然后程序从最后一个catch处理之后开始恢复
- 栈的展开
#include <fstream>
#include <iostream>
using namespace std;
class expt // 基类,外层构造
{
private:
/* data */
public:
expt(/* args */);
~expt();
};
expt::expt(/* args */)
{
cout << "construction of expt" << endl;
}
expt::~expt()
{
cout << "destruction of expt" << endl;
}
class demo
{
private:
/* data */
public:
demo(/* args */);
~demo();
};
demo::demo(/* args */) // 派生类,内层构造
{
cout << "construction of demo" << endl;
}
demo::~demo()
{
cout << "destruction of demo" << endl;
}
void fun1()
{
int s = 0;
demo d;
throw s; // 抛出异常
}
void fun2()
{
expt e;
fun1();
}
int main(int argc, char const *argv[])
{
try // 定义异常
{
fun2();
}
catch(int) // 异常处理
{
std::cerr << "catch int exception" << '\n';
}
cout << "complete" << endl;
return 0;
}
实现结果:
处理结构类型的异常
主要要注意的是throw语句中用结构类型,catch的参数同样为结构类型
#include <fstream>
#include <iostream>
#include <string.h>
using namespace std;
class expt // 基类,外层构造
{
private:
/* data */
public:
expt(/* args */);
~expt();
};
expt::expt(/* args */)
{
cout << "construction of expt" << endl;
}
expt::~expt()
{
cout << "destruction of expt" << endl;
}
class demo
{
private:
/* data */
public:
demo(/* args */);
~demo();
};
demo::demo(/* args */) // 派生类,内层构造
{
cout << "construction of demo" << endl;
}
demo::~demo()
{
cout << "destruction of demo" << endl;
}
void fun1()
{
int s = 0;
demo d;
throw s; // 抛出异常
}
void fun2()
{
expt e;
fun1();
}
struct aircraft
{
char *aircrafttype;
float len;
};
void fun3()
{
aircraft a;
a.aircrafttype = "queen";
// 这样赋值会给warning,因为实际上是不对的,最好用下面两行,然后再加一个while循环逐位赋值
// a.aircrafttype = new char[strlen("queen")];
// const char *temp = "queen";
a.len = 25;
throw a;
}
int main(int argc, char const *argv[])
{
try // 定义异常
{
fun3();
}
catch(aircraft b) // 异常处理
{
cerr << "aircraft type is: " << b.aircrafttype << '\n';
}
cout << "complete" << endl;
return 0;
}
运行结果
从结果可以看出,catch之后,原有对象的data被拷贝到了新定义的结构体b里面