异常类型和异常变量的生命周期
1)throw的异常是有类型的,可以使,数字、字符串、类对象。
2)throw的异常是有类型的,catch严格按照类型进行匹配。
3)注意 异常对象的内存模型 。
一、 传统处理错误
//文件的二进制copy int filecopy01(char *filename2, char *filename1 ) { FILE *fp1= NULL, *fp2 = NULL; fp1 = fopen(filename1, "rb"); if (fp1 == NULL) { return 1; } fp2 = fopen(filename2, "wb"); if (fp1 == NULL) { return 2; } char buf[256]; int readlen, writelen; while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen != readlen) { return 3; } } fclose(fp1); fclose(fp2); return 0; } 测试程序 void main() { int ret; ret = filecopy01("c:/1.txt","c:/2.txt"); if (ret !=0 ) { switch(ret) { case 1: printf("打开源文件时出错!\n"); break; case 2: printf("打开目标文件时出错!\n"); break; case 3: printf("拷贝文件时出错!\n"); break; default: printf("发生未知错误!\n"); break; } } }
二、throw int类型异常
/文件的二进制copy void filecopy02(char *filename2, char *filename1 ) { FILE *fp1= NULL, *fp2 = NULL; fp1 = fopen(filename1, "rb"); if (fp1 == NULL) { //return 1; throw 1; } fp2 = fopen(filename2, "wb"); if (fp1 == NULL) { //return 2; throw 2; } char buf[256]; int readlen, writelen; while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen != readlen) { //return 3; throw 3; } } fclose(fp1); fclose(fp2); return ; }
三、throw字符类型异常
//文件的二进制copy void filecopy03(char *filename2, char *filename1 ) { FILE *fp1= NULL, *fp2 = NULL; fp1 = fopen(filename1, "rb"); if (fp1 == NULL) { throw "打开源文件时出错"; } fp2 = fopen(filename2, "wb"); if (fp1 == NULL) { throw "打开目标文件时出错"; } char buf[256]; int readlen, writelen; while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen != readlen) { throw "拷贝文件过程中失败"; } } fclose(fp1); fclose(fp2); return ; }
四、throw类对象类型异常
//throw int类型变量 //throw 字符串类型 //throw 类类型 class BadSrcFile { public: BadSrcFile() { cout << "BadSrcFile 构造 do "<<endl; } ~BadSrcFile() { cout << "BadSrcFile 析构 do "<<endl; } BadSrcFile(BadSrcFile & obj) { cout << "拷贝构造 do "<<endl; } void toString() { cout << "aaaa" << endl; } }; class BadDestFile {}; class BadCpyFile {};; void filecopy04(char *filename2, char *filename1 ) { FILE *fp1= NULL, *fp2 = NULL; fp1 = fopen(filename1, "rb"); if (fp1 == NULL) { //throw new BadSrcFile(); throw BadSrcFile(); } fp2 = fopen(filename2, "wb"); if (fp1 == NULL) { throw BadDestFile(); } char buf[256]; int readlen, writelen; while ( (readlen = fread(buf, 1, 256, fp1)) > 0 ) //如果读到数据,则大于0 { writelen = fwrite(buf, 1, readlen, fp2); if (readlen != readlen) { throw BadCpyFile(); } } fclose(fp1); fclose(fp2); return ; }
main测试案例 //结论://C++编译器通过throw 来产生对象,C++编译器再执行对应的catch分支,相当于一个函数调用,把实参传递给形参。 void main() { try { //filecopy02("c:/1.txt","c:/2.txt"); // filecopy03("c:/1.txt","c:/2.txt"); filecopy04("c:/1.txt","c:/2.txt"); } catch (int e) { printf("发生异常:%d \n", e); } catch (const char * e) { printf("发生异常:%s \n", e); } catch ( BadSrcFile *e) { e->toString(); printf("发生异常:打开源文件时出错!\n"); } catch ( BadSrcFile &e) { e.toString(); printf("发生异常:打开源文件时出错!\n"); } catch ( BadDestFile e) { printf("发生异常:打开目标文件时出错!\n"); } catch ( BadCpyFile e) { printf("发生异常:copy时出错!\n"); } catch(...) //抓漏网之鱼 { printf("发生了未知异常! 抓漏网之鱼\n"); } //class BadSrcFile {}; //class BadDestFile {}; //class BadCpyFile {};; }
异常的层次结构(继承在异常中的应用)
1.异常是类 – 创建自己的异常类
2.异常派生
3.异常中的数据:数据成员
4.按引用传递异常
-->在异常中使用虚函数
五、标准程序库异常
案例1: #include "iostream" using namespace std; #include <stdexcept> class Teacher { public: Teacher(int age) //构造函数, 通过异常机制 处理错误 { if (age > 100) { throw out_of_range("年龄太大"); } this->age = age; } protected: private: int age; }; void mainxx() { try { Teacher t1(102); } catch (out_of_range e) { cout << e.what() << endl; } exception e; system("pause"); }
案例2 class Dog { public: Dog() { parr = new int[1024*1024*100]; //4MB } private: int *parr; }; int main31() { Dog *pDog; try{ for(int i=1; i<1024; i++) //40GB! { pDog = new Dog(); cout << i << ": new Dog 成功." << endl; } } catch(bad_alloc err) { cout << "new Dog 失败: " << err.what() << endl; } return 0; }
案例3