第十三站:C++异常处理机制

概念:

   函数是一种以栈结构展开的上下函数衔接的程序控制系统
,异常是另一种控制结构,
它可以在出现“意外”时中断当前函数,
并以某种机制(类型匹配)回馈给隔代的调用者相关的信息.

异常处理的基本语法

异常发生第一现场,抛出异常,中断程序

void function( ){

        //... ...

        throw 表达式
;

        //... ...

}

在需要关注异常的地方,捕捉异常

try{

        //程序

        function();

        //程序

}catch(
异常类型声明
){

        //... 异常处理代码
...

}catch(
异常类型 形参
){

        //... 异常处理代码
...

}catch(...){ //
其它异常类型

        //

}


通过
throw 操作创建一个异常对象并抛掷


在需要捕捉异常的地方,将
可能抛出异常的程序段嵌在 try
块之中

③按正常的程序顺序执行到达
try
语句,然后执行
try

{}
内的保护段,如果
有匹配的时候才会执行catch
语句抛出异常,中断程序(以函数体为单位)

④如果没有找到匹配,则
缺省功能是调用 abort 终止
程序。

int
copyfile2(
char
*dest,
char
*src){

        FILE *fp1 = NULL, *fp2 = NULL;

        //rb 只读方式打开一个二进制文件,只允许读取数据

        fopen_s(&fp1, src,
"rb"
);

        if
(fp1 == NULL){

                throw
new string
(
"文件不存在"
);//这里抛出一个指针

        }

        

        fopen_s(&fp2, dest,
"wb"
);

        if
(fp2 == NULL){

                throw
-2;

        }

}

int main(void){

        int
ret = 0;

        try
{

                ret = copyfile1(
"c:/test/dest.txt"
,
"c:/test/src.txt"
);

        }
catch
(
int
error){  //catch(int)只接受到int值

                printf(
"出现异常啦!%d
"
, error);

        }
catch
(string *error){
//用指针接收string

                printf(
"捕捉到字符串异常:%s
"
, error->c_str());

        delete
error;

        }

}

异常接口声明

 int copyfile2(char *dest, char *src) throw (float, string *, int)

在函数声明中列出可能抛出的所有异常类型,,,没有包含异常接口声明,此函数可以抛出任何类型的异常.如果产生异常声明之外的其它类型的异常就可能导致程序终止.

如果不想抛出任何异常,那么就使用throw();

异常类型和生命周期

 

 异常基础类型:

catch (int error) {
    printf("出现异常啦!%d
", error);
}
catch (char error) {
    printf("出现异常啦!%c
", error);
}

异常字符串类型 

if
(fp1 == NULL){

        throw new
string(
"文件不存在"
);

}

        catch
(string *error){

        printf(
"捕捉到字符串异常:%s
"
, error->c_str());

        delete
error;

}

异常类类型

if
(fp1 == NULL){

        //ErrorException error1;

        throw
ErrorException();
//throw ErrorException();

        //指针 throw new 
ErrorException(); 

}

        catch
(ErrorException &error){

        //error.id = 2;

        printf(
"出现异常啦!捕捉到 ErrorException &类型 id: %d
"
,

        error.id);

        }
catch
(ErrorException *error){

        printf(
"出现异常啦!捕捉到 ErrorException *类型 id: %d
"
,

        error->id);

        delete
error;

}

异常和继承练习(使用多态)

案例:设计一个数组类容器
Vector
,重载
[]
操作,数组初始化时,对数组的个数进行有效检

1

index<0
抛出异常
errNegativeException

2

index = 0
抛出异常
errZeroException

3

index>1000
抛出异常
errTooBigException

4

index<10
抛出异常
errTooSmallException

5)  
errSizeException
类是以上类的父类,实现有参数构造、并定义
virtual void printError()

 

#include <iostream>
using namespace std;
/*
1)index<0 抛出异常 errNegativeException
2)index = 0 抛出异常 errZeroException
3)index>1000 抛出异常 errTooBigException
4)index<10 抛出异常 errTooSmallException
5) errSizeException 类是以上类的父类,实现有参数构造、并定义 virtual void printError()
*/
class errSizeException {
public:
	errSizeException(int len) {
		this->len = len;
	};
	virtual void printError() {
		cout << "errSizeException:size:" << len << endl;
	};
protected:
	int len;
};
//index<0
class errNegativeException:public errSizeException {
public:
	//errNegativeException();
	errNegativeException(int len):errSizeException(len){};
	virtual void printError() {
		cout << "errNegativeException:size:" << len << endl;
	};
};
//index = 0
class errZeroException :public errSizeException {
public:
	//errZeroException();
	errZeroException(int len) :errSizeException(len) {};
	virtual void printError() {
		cout << "errZeroException:size:" << len << endl;
	};
};
//index>1000
class errTooBigException :public errSizeException {
public:
	//errTooBigException();
	errTooBigException(int len) :errSizeException(len) {};
	virtual void printError() {
		cout << "errTooBigException:size:" << len << endl;
	};
};
//index<10
class errTooSmallException :public errSizeException {
public:
	//errTooSmallException();
	errTooSmallException(int len) :errSizeException(len) {};
	virtual void printError() {
		cout << "errTooSmallException:size:" << len << endl;
	};
};
class Vector {
public:
	//构造函数
	Vector(int len) {
		if (len<0){
			throw errNegativeException(len);
		}
		else if (len == 0) {
			throw errZeroException(len);
		}
		else if (len > 1000) {
			throw errTooBigException(len);
		}
		else if (len < 10) {
			throw errTooSmallException(len);
		}
		this->len = len;
		m_len = new int(len);
	}
	int getLen() {
		return len;
	}
	//析构函数
	~Vector() {
		if (!m_len){
			delete[] m_len;
			m_len = NULL;
			len = 0;
		}
	}
	//下标运算符重载
	int& operator[](int dex) {
		return m_len[dex];
	}

private:
	int len;
	int* m_len;
};

int main(void) {
	try{
		Vector aa(-10);
		for (int i = 0; i < aa.getLen(); i++){
			aa[i] = i;
		}
	}
	catch(errSizeException err){
		err.printError();
	}
	/*catch (errNegativeException &err){
		cout << "errNegativeException:size" << endl;
	}*/
}

C++标准库的各类异常所代表的异常

谨慎尝试以下代码:

#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
class Student {
public:
	Student(int age) {
		if (age > 249) {
			throw out_of_range("年龄太大,你是外星人嘛?");
		}
		m_age = age;
		m_space = new int[1024 *1024 * 100];
	}
private:
	int m_age;
	int* m_space;
};
void main() {
	try {
		for (int i = 1; i < 1024; i++) {
			Student* xiao6lang = new Student(18);
		}
	}
	catch (out_of_range& e) {
		cout << "捕捉到一只异常:" << e.what() << endl;
	}
	catch (bad_alloc& e) {
		cout << "捕捉到动态内存分配的异常:" << e.what() << endl;
	}
	system("pause");
}