目录
1、异常基本语法
- try 试图执行 try{}中的内容
- 在可能出现异常的地方 抛出异常 throw
- try下面 catch捕获异常
- catch( 捕获类型 ) …代表 所有其他类型
- 如果不想处理异常,继续向上抛出 throw
- 如果没有任何处理异常的地方,那么成员调用terminate函数,中断程序
- 自定义异常类 ,可以抛出自定义的对象 ,捕获自定义的异常
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int myDevide(int a, int b)
{
if (b == 0)
{
//如果b是异常 抛出异常
//return - 1;
//throw - 1;
//throw 1; 抛出int类型的异常
throw 3.14; //抛出double类型的异常 异常必须处理,如果不处理就挂掉
//throw 'a';
}
return a / b;
}
void test01()
{
int a = 10;
int b = 0;
//int ret = myDevide(a, b); //早期如果返回-1 无法区分到底是结果还是异常
//C++中异常处理
try //尝试
{
myDevide(a, b);
}
catch (int) //捕获异常
{
cout << "int类型异常捕获" << endl;
}
catch (double) //捕获异常
{
//如果不想处理这个异常 就向上抛出
throw;
cout << "double类型异常捕获" << endl;
}
catch (...)
{
cout << "其他类型异常捕获" << endl;
}
}
int main(void)
{
try
{
test01();
}
catch (char) //如果异常都没有处理,那么成员terminate函数,使程序中断
{
cout << "main函数中char异常捕获" << endl;
}
catch (...)
{
cout << "main中其他类型异常捕获" << endl;
}
system("pause");
return 0;
}
自定义异常
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//自定义异常类
class myException
{
public:
void printError()
{
cout << "自定义异常" << endl;
}
};
int myDevide(int a, int b)
{
if (b == 0)
{
//如果b是异常 抛出异常
//return - 1;
//throw - 1;
//throw 1; 抛出int类型的异常
//throw 3.14; //抛出double类型的异常 异常必须处理,如果不处理就挂掉
//throw 'a';
throw myException(); //匿名对象
}
return a / b;
}
void test01()
{
int a = 10;
int b = 0;
//int ret = myDevide(a, b); //早期如果返回-1 无法区分到底是结果还是异常
//C++中异常处理
try //常试
{
myDevide(a, b);
}
catch (int) //捕获异常
{
cout << "int类型异常捕获" << endl;
}
catch (double) //捕获异常
{
//如果不想处理这个异常 就向上抛出
throw;
cout << "double类型异常捕获" << endl;
}
catch (myException e)
{
e.printError();
}
catch (...)
{
cout << "其他类型异常捕获" << endl;
}
}
int main(void)
{
try
{
test01();
}
catch (char) //如果异常都没有处理,那么成员terminate函数,使程序中断
{
cout << "main函数中char异常捕获" << endl;
}
catch (...)
{
cout << "main中其他类型异常捕获" << endl;
}
system("pause");
return 0;
}
2、栈解旋
异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反,这一过程称为栈的解旋(unwinding)。
- 从try开始 到 throw 抛出异常之前 所有栈上的对象 都会被释放 这个过程称为栈解旋
- 栈上对象构造顺序与析构顺序相反
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//自定义异常类
class myException
{
public:
void printError()
{
cout << "自定义异常" << endl;
}
};
class Person
{
public:
Person()
{
cout << "Person构造" << endl;
}
~Person()
{
cout << "Person析构" << endl;
}
};
int myDevide(int a, int b)
{
if (b == 0)
{
//如果b是异常 抛出异常
//return - 1;
//throw - 1;
//throw 1; 抛出int类型的异常
//throw 3.14; //抛出double类型的异常 异常必须处理,如果不处理就挂掉
//throw 'a';
//栈解旋
//从try开始 到throw抛出异常之前 所有栈上的对象 都会被释放 这个过程称为栈解旋
//构造和析构顺序相反
Person p1;
Person p2;
throw myException(); //匿名对象
}
return a / b;
}
void test01()
{
int a = 10;
int b = 0;
//int ret = myDevide(a, b); //早期如果返回-1 无法区分到底是结果还是异常
//C++中异常处理
try //常试
{
myDevide(a, b);
}
catch (int) //捕获异常
{
cout << "int类型异常捕获" << endl;
}
catch (double) //捕获异常
{
//如果不想处理这个异常 就向上抛出
throw;
cout << "double类型异常捕获" << endl;
}
catch (myException e)
{
e.printError();
}
catch (...)
{
cout << "其他类型异常捕获" << endl;
}
}
int main(void)
{
try
{
test01();
}
catch (char) //如果异常都没有处理,那么成员terminate函数,使程序中断
{
cout << "main函数中char异常捕获" << endl;
}
catch (...)
{
cout << "main中其他类型异常捕获" << endl;
}
system("pause");
return 0;
}
3、异常的接口声明
- 如果想抛出特定的类型异常 ,可以利用异常的接口声明
- void func() throw ( int) 只能抛出 int类型
- throw() 不抛出任何类型异常
4、异常变量的生命周期
- 如果 MyException e,会多开销一份数据 ,调用拷贝构造
- 如果 MyExcepiton *e , 不 new提前释放对象 new 自己管理delete
- 推荐 MyException &e 容易些 而且 就一份数据
#define _CRT_SECURE_NO_WRNINGS
#include<iostream>
using namespace std;
class MyException
{
public:
MyException()
{
cout << "MyException默认构造" << endl;
}
MyException(const MyException & e)
{
cout << "MyException拷贝构造" << endl;
}
~MyException()
{
cout << "MyException析构" << endl;
}
};
void doWork()
{
throw MyException();
}
void test01()
{
try
{
doWork();
}
catch (MyException &e) //MyException e 会多开销一份数据,利用引用提高效率
{
cout << "捕获异常" << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
MyException e的结果:
MyException &e的结果:
如果使用指针变量,需要自己delete,否则出现下面的结果
#define _CRT_SECURE_NO_WRNINGS
#include<iostream>
using namespace std;
class MyException
{
public:
MyException()
{
cout << "MyException默认构造" << endl;
}
MyException(const MyException & e)
{
cout << "MyException拷贝构造" << endl;
}
~MyException()
{
cout << "MyException析构" << endl;
}
};
void doWork()
{
throw new MyException();
}
void test01()
{
try
{
doWork();
}
catch (MyException *e)
{
cout << "捕获异常" << endl;
delete e; //靠自觉 释放对象
}
}
int main()
{
test01();
system("pause");
return 0;
}
5、异常的多态使用
- 利用多态来实现 printError同一个接口调用
- 抛出不同的错误对象,提示不同错误
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//异常基类
class BaseException
{
public:
virtual void printError()
{
}
};
class NullPinterException :public BaseException
{
public:
virtual void printError()
{
cout << "空指针异常" << endl;
}
};
class OutofRangeException :public BaseException
{
public:
virtual void printError()
{
cout << "越界异常" << endl;
}
};
void doWork()
{
//throw NullPinterException();
throw OutofRangeException();
}
void test01()
{
try
{
doWork();
}
catch (BaseException& e)
{
e.printError();
}
}
int main()
{
test01();
system("pause");
return 0;
}
6、使用系统标准异常
- #incldue <stdexcept>
- throw out_of_range(”aaa”) 。。。
- catch(out_of_range & e) cout << e.what();
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
//系统提供标准异常 要包含头文件
#include<stdexcept>
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
//年龄检测
if (age<0 || age>200)
{
//抛出越界异常
//throw out_of_range("年龄越界了!");
throw length_error("长度越界");
}
}
string m_Name;
int m_Age;
};
void test01()
{
try
{
Person p("张三", 300);
}
catch (out_of_range &e)
{
cout << e.what() << endl;
}
catch (length_error &e)
{
cout << e.what() << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
7、编写自己的异常类
- 自己的异常类 需要继承于 exception
- 重写 虚析构 what()
- 内部维护以错误信息 字符串
- 构造时候传入 错误信息字符串,what返回这个字符串
- string 转 char * .c_str();
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
using namespace std;
class MyOutOfRangeException :public exception
{
public:
MyOutOfRangeException(string errorInfo)
{
this->m_ErrorInfo = errorInfo;
}
virtual ~MyOutOfRangeException()
{
}
virtual const char * what() const
{
//返回错误信息
//string转char* + .c_str()
return this->m_ErrorInfo.c_str();
}
string m_ErrorInfo;
};
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
//年龄检测
if (age<0 || age>200)
{
//抛出异常
throw MyOutOfRangeException(string("我自己的年龄越界异常"));
}
}
string m_Name;
int m_Age;
};
void test01()
{
try
{
Person p("zhang", 300);
}
catch (MyOutOfRangeException &e)
{
cout << e.what();
}
}
int main()
{
test01();
system("pause");
return 0;
}