异常可以跨函数
异常必须处理
1、
#include<iostream>
using namespace std;
//c++异常机制 跨函数
//c++异常必须处理 不能留,否则报错
int divided(int x, int y)
{if (y == 0)throw y; //抛异常return (x / y);
}
void test01()
{int x = 10, y = 0;//试着去捕获异常try{divided(x, y);}catch (int y) //异常是根据类型进行匹配{cout << "除数为" << y <<"!"<< endl;}
}void CallDivide(int x, int y)
{divided(x, y);
}
//如果异常抛到顶层,还没有处理这个时候程序后挂掉terminal()
//a调用b,b调用c,c调用d函数 a-->b-->c-->d
//d抛出异常,c没有处理,则继续给b,b还没有处理给a,则异常给a,a处理(catch)即可。若a还不处理,则报错,程序挂掉
void test02() {try{CallDivide(1, 0);}catch (int e){cout << "除数为" << e << endl;}
}
int main()
{test01();cout << "------------------" << endl;test02();
}
2、栈解旋
#include<iostream>
using namespace std;class person {
public:person(){cout << "对象构建" << endl;}~person(){cout << "对象析构" << endl;}};int divide(int x, int y)
{person p1, p2;if (y == 0)throw y;return x / y;
}
//栈解旋:try catch中调用函数发生异常时,函数内的局部变量会被析构掉
void test01()
{try {divide(10, 0);}catch (int e){cout << "异常捕获!" << endl;}
}int main()
{test01();return 0;
}
3、异常接口的声明
#include<iostream>
using namespace std;
//这个函数只能抛出int,float,char三种类型异常,抛出其他报错
void func() throw(int, float, char)
{throw "abc";
}
//不能抛出任何类型异常
void func02() throw()
{throw - 1;
}
//抛出任何类型异常
void func03()
{throw - 2;
}
int main()
{try {func();}catch (char* str){cout << str << endl;}catch (int e){cout << "异常!" << endl;}catch (...) //...代表所有异常类型{cout << "捕获所有未知类型异常" << endl;}
}
4、异常类型
#include<iostream>
using namespace std;void func01(){throw 1; //抛出int类型异常
}
void func02() {throw "exception"; //抛出char*类型异常
}
class MyException {
public:MyException(char* str) {error = new char[strlen(str) + 1];strcpy(error, str);}void what() {cout << error << endl;}MyException(const MyException& ex){ //拷贝构造this->error = new char[strlen(ex.error) + 1];strcpy(this->error, ex.error);}MyException& operator=(const MyException& ex) { //等于构造if (this->error != NULL){delete[] this->error;this->error = NULL;}this->error = new char[strlen(ex.error) + 1];strcpy(this->error, ex.error);}MyException(){if (error != NULL){delete[] error;}}
public:char* error;
};
void func03() {throw MyException("我刚写的异常!");
}
void test01(){try {func01();}catch (int e) {cout << "异常捕获!" << endl;}
//----------------------------------------try {func02();}catch (char* e) {cout << "异常捕获!" << endl;}
//-----------------------------------------try {func03();}catch (MyException e) {e.what();}
}int main()
{MyException e1=MyException("dd"); //拷贝构造MyException e2 = e1; //等于构造test01();return 0;
}
运行结果:
5、异常生命周期
#include<iostream>
using namespace std;class MyException {
public:MyException() {cout << "构造函数" << endl;}MyException(const MyException& ex) { //拷贝构造cout << "拷贝构造函数" << endl;}~MyException() {cout << "析构函数" << endl;}};
void func() {//throw MyException(); //创建匿名对象,调用构造函数//throw &(MyException()); //创建匿名对象,调用构造函数throw new MyException();
}
void test01() {//普通类型元素 引用 指针//普通类型元素 catch处理完后就析构//引用的话 不用调用拷贝构造 catch处理完后就析构//指针的话,需要new一个异常,否则在捕捉异常前就已经析构try {func();}//catch (MyException e) { //用MyException元素接,相当于将上面的MyException()拷贝一份传给e,调用拷贝构造// cout << "异常捕获" << endl;//}//catch (MyException& e) { //用MyException元素接,相当于将上面的MyException()拷贝一份传给e,调用拷贝构造// cout << "异常捕获" << endl;//}catch (MyException* e) { //用MyException元素接,相当于将上面的MyException()拷贝一份传给e,调用拷贝构造cout << "异常捕获" << endl;delete e;}
}int main()
{test01();return 0;
}
运行结果:
6、c++异常库举例
#include<iostream>
#include<stdexcept>
using namespace std;class Person {
public:Person() {mAge = 0;}void setAge(int age){if (age < 0 || age>100) {throw out_of_range("年龄在0-100之间!");}this->mAge = age;}
public:int mAge;
};
void test01(){Person p;try {p.setAge(1000);}catch (out_of_range e) {cout << e.what() << endl;}catch (exception e) {cout << e.what() << endl;}
}class MyOutOfRange : public exception {
public:MyOutOfRange(char* error) {pError = new char[strlen(error) + 1];strcpy(pError, error);}virtual char const* what() const {return pError;}MyOutOfRange() {if (pError != NULL) {delete[] pError;}}
public:char* pError;
};
void func02() {throw MyOutOfRange("我自己抛出的异常");
}
void test02() {try {func02();}catch (exception& e) {cout << e.what() << endl;}
}
int main() {test01();test02();return 0;
}
运行结果:
7、继承在异常中的应用
#include<iostream>
using namespace std;//异常基类
class BaseMyException {
public:virtual void what()=0;virtual ~BaseMyException() {};
};
class TargetSpaceNullException :public BaseMyException {
public:virtual void what() {cout << "目标空间为空!" << endl;}~TargetSpaceNullException(){}
};
class SourceSpaceNullException :public BaseMyException {
public:virtual void what() {cout << "源空间为空" << endl;}~SourceSpaceNullException() {}
};void copy_str(char* target, char* source){if (target == NULL){//cout << "目标空间为空" << endl;throw TargetSpaceNullException();return;}if (source == NULL) {throw SourceSpaceNullException();//cout << "源空间为空" << endl;return;}int len = strlen(source)+1;while (*source != '\0') {*target = *source;source++;target++;}
}int main()
{char* source = "abcdefg";char buf[1024] = { 0 };cout << "copy" << endl;try {copy_str(NULL, source);}catch (BaseMyException& e) {e.what();}cout << buf << endl;return 0;
}