您的位置:首页 > 编程语言 > C语言/C++

C++学习笔记:异常的基本语法

2016-03-05 10:32 483 查看
1)若有异常 则通过throw 操作 创建一个异常对象 并抛出。

2)将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句。然后执行try块内的保护段

3)如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去

4)catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛出异常)

5)如果匹配的处理器未找到,则运行函数terminate将被自动调用,其缺省功能是调用abort终止程序

6)处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔

// 异常的基本语法.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

void divide(int x,int y){
if (y == 0){
throw x;//抛出 int 类型异常
//异常直接跨越函数,类似于return语句,不执行接下来的语句
}
cout << "divide结果:" << x / y << endl;
}

void myDivide(int x, int y){
try{
divide(x, y);
}
catch (...){
cout << "我接受了divide的异常,但是我没有处理,我继续向上抛出" << endl;
throw;//接受异常后可以不处理,继续抛出
}
}

int _tmain(int argc, _TCHAR* argv[])
{
try{
divide(10 , 2);
divide(100 , 0);
//myDivide(1, 0);//跨越函数的实验
}
catch (int e){
cout << e << "被零整除" << endl;
}
catch (...){//其他未知类型的异常
cout << "其他未知类型异常" << endl;
}

return 0;
}




2.栈解旋

执行throw语句后,相当于 return ,但是不是,会调用析构函数 释放掉栈空间

// 异常_栈解旋.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class Test{
public:
Test(int a = 0, int b = 0){
this->a = a;
this->b = b;
cout << "构造函数do" << endl;
}
~Test(){
cout << "析构函数do\n";
}
private:
int a;
int b;
};

void myDivide(){
Test t1(1, 2), t2(3, 4);
cout << "myDivide 要发生异常啦~ " << endl;
throw 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
try{
myDivide();
}
catch (int a){
cout << "int型异常" << endl;
}
catch (...){
cout << "未知异常" << endl;
}
return 0;
}




3.异常的接口声明

1)为了加强程序的可读性,可以在函数声明中列出可能抛出的所有异常累成,例如:

void func() throw(A,B,C,D);//这个函数func()能够且只能抛出类型A B C D及其子类型的异常

2)如果在函数声明中没有包含异常接口声明,则该函数可以抛出任何类型的异常,例如:

void func();

3)一个不抛出任何类型异常的函数可以声明为:

void func() throw();

4)如果一个函数抛出了它的异常接口声明所不允许抛出的异常,unexpercted函数会被调用,该函数默认行为调用terminate函数终止程序。

4.异常变量的声明周期

// 异常_栈解旋.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class BadSrcType{
public:
BadSrcType(){
cout << "BadSrcType构造函数do" << endl;
}
BadSrcType(const BadSrcType &obj){
cout << "BadSrcType拷贝构造函数do" << endl;
}
~BadSrcType(){
cout << "BadSrcType析构函数do\n";
}
};

class BadDesType{
public:
BadDesType(){
cout << "BadDesType构造函数do" << endl;
}
BadDesType(const BadDesType &obj){
cout << "BadDesType拷贝构造函数do" << endl;
}
~BadDesType(){
cout << "BadDesType析构函数do\n";
}
};

class BadProType{
public:
BadProType(){
cout << "BadProType构造函数do" << endl;
}
BadProType(const BadProType &obj){
cout << "BadProType拷贝构造函数do" << endl;
}
~BadProType(){
cout << "BadProType析构函数do\n";
}
};

void my_strcpy(char *to,char *from){
if (from == NULL){
throw BadSrcType();//会产生一个匿名对象
}
if (to == NULL){
throw BadDesType();
}

if (*from=='a'){
cout << "开始BadProType类型异常" << endl;
throw BadProType();//适用于方式一和二
//throw new BadProType;//适用于方式三
}
while (*from!='\0'){
*to = *from;
to++;
from++;
}
*to = '\0';
}

int main()
{
int ret = 0;
char buf1[] = "abcdefg";
char buf2[1024] = { 0 };
try{
my_strcpy(buf2,buf1);
}
//结论1:如果接收异常的时候使用异常变量 则进行拷贝构造异常变量
catch (BadSrcType e){//接匿名对象,并初始化e,此时匿名对象转正,不会调用匿名对象的析构函数
cout << "BadSrcType类型异常" << endl;
}
catch (BadDesType e){
cout << "BadDesType类型异常" << endl;
}
catch (BadProType e){
cout << "BadProType类型异常" << endl;
}
catch (...){
cout << "未知异常" << endl;
}
//方式二:用引用接收异常
//结论二:使用引用的话 会使用throw时候的那个对象
//catch (BadSrcType &e){//接匿名对象,并初始化e,此时匿名对象转正,不会调用匿名对象的析构函数
//	cout << "BadSrcType类型异常" << endl;
//}
//catch (BadDesType &e){
//	cout << "BadDesType类型异常" << endl;
//}
//catch (BadProType &e){
//	cout << "BadProType类型异常" << endl;
//}
//catch (...){
//	cout << "未知异常" << endl;
//}
//方式三:用指针来接
//结论三:指针可以和引用/元素 写在一块,但是元素和引用不能写在一块
//catch (BadSrcType *e){//接匿名对象,并初始化e,此时匿名对象转正,不会调用匿名对象的析构函数
//	cout << "BadSrcType类型异常" << endl;
//	delete e;//在底层函数里new,在上层函数里delete。不安全
//}
//catch (BadDesType *e){
//	cout << "BadDesType类型异常" << endl;
//	delete e;
//}
//catch (BadProType *e){
//	cout << "BadProType类型异常" << endl;
//	delete e;
//}
//catch (...){
//	cout << "未知异常" << endl;
//}
//结论:最适合的方法是用引用来接
return 0;
}
方式一:



方式二:



方式三:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: