异常
1、异常的概述
常见的异常:除0溢出,数组下标越界,所要读取的文件不存在,空指针,内存不足等等。
c++的异常一旦抛出 如果不捕获 该异常 程序直接退出
1.1、C语言通过返回值 来判断 第一:容易忽略 第二:容易和正常的结果混淆
int myDiv(int a,int b)
{
if(b == 0)
return -1;//-1表示失败
return a/b;
}
void test01()
{
int ret = myDiv(10,-10);
if(ret == -1)
{
cout<<"程序异常了"<<endl;
}
else
{
cout<<"程序正常"<<endl;
}
}
运行结果:
1.2、c++抛出异常 并捕获
c++的异常一旦抛出 如果不捕获 该异常 程序直接退出
抛出异常:throw
捕获异常:try…catch
int myDiv01(int a,int b)
{
if(b==0)
throw 0;//抛出异常
return a/b;
}
void test02()
{
try{
int ret = myDiv01(10,0);
cout<<"ret = "<<ret<<endl;
}
#if 1
catch(int e)//只捕获 抛出是int类型的异常
{
cout<<"捕获到int类型异常 e = "<<e<<endl;
}
#endif
catch(float e)//只捕获 抛出是float类型的异常
{
cout<<"捕获到float类型异常 e = "<<e<<endl;
}
catch(char e)//只捕获 抛出是char类型的异常
{
cout<<"捕获到char类型异常 e = "<<e<<endl;
}
#if 0
catch(...)
{
cout<<"捕获到其他异常"<<endl;
}
#endif
cout<<"程序做其他事情"<<endl;
}
运行结果:
2、栈解旋(unwinding)
异常被抛出后,从进入try块起,到异常被抛掷前,这期间在栈上构造的所有对象,都会被自动析构。析构的顺序与构造的顺序相反,这一过程称为栈的解旋(unwinding).
void test03()
{
try{
Person ob1("00_德玛");
Person ob2("01_小炮");
Person ob3("02_小法");
Person ob4("03_提莫");
throw 10;
}
catch(int)
{
cout<<"捕获到int异常"<<endl;
}
cout<<"其他工作"<<endl;
}
运行结果:
3、异常的接口声明
throw(int,char,char*) 只抛出int、char、char *异常
void testFunc01()
{
//函数内部可以抛出任何异常
//throw 10;
//throw 4.3f;
//throw 'a';
//throw "hehe";
string ob="heihie";
throw ob;
}
//只能抛出int char 异常
void testFunc02() throw(int,char)
{
throw 3.14f;
}
//函数 不抛出任何异常
void testFunc03()throw()
{
throw 10;//外部捕获 不到
}
void test04()
{
try{
testFunc03();
}
catch(int e)//只捕获 抛出是int类型的异常
{
cout<<"捕获到int类型异常 e = "<<e<<endl;
}
catch(float e)//只捕获 抛出是float类型的异常
{
cout<<"捕获到float类型异常 e = "<<e<<endl;
}
catch(char e)//只捕获 抛出是char类型的异常
{
cout<<"捕获到char类型异常 e = "<<e<<endl;
}
catch(char const *e)//只捕获 抛出是char *类型的异常
{
cout<<"捕获到char const *类型异常 e = "<<e<<endl;
}
catch(string e)
{
cout<<"捕获到string类型异常 e = "<<e<<endl;
}
}
4、异常的生命周期 的三种情况
4.1、以普通变量形式捕获
class MyException
{
public:
MyException()
{
cout << "异常变量构造" << endl;
};
MyException(const MyException & e)
{
cout << "拷贝构造" << endl;
}
~MyException()
{
cout << "异常变量析构" << endl;
}
};
void text() //抛出异常
{
MyException ob;
throw ob;
}
void test01()
{
try {
text();
} catch (MyException e) {
cout << "捕获到MyException异常" <<endl;
}
}
运行结果:
4.2、以指针形式捕获
void test02()
{
try {
//text();
throw new MyException;
} catch (MyException *e) {
cout << "捕获到MyException *异常" <<endl;
delete e; //必须记得释放e
}
}
运行结果:
4.3、以引用形式捕获(推荐使用)
void test03()
{
try {
//text();
throw MyException();
} catch (MyException &e) {
cout << "捕获到MyException &异常" <<endl;
}
}
5、标准异常
案例
class Person2
{
private:
int age;
public:
Person2(int age)
{
if(age<0 || age >150)
throw out_of_range("age无效");
this->age =age;
}
};
void test06()
{
try{
Person2 ob(200);
}
catch(exception &e)
{
cout<<"捕获到异常"<<e.what()<<endl;
//e.what() : age无效
}
}