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