我们在c++异常机制(3)中自定义类型,我们将相应的异常封装成了类,在类中实现一些方法,对异常进行处理。其中每一个类都实现了print()方法。
我们使用throw抛出相应异常的虚拟对象,在catch参数中进行匹配,但是如果有很多异常类型,我们就需要写很多的catch进行匹配,能否只写一个catch就可以匹配不同的异常类,并且调用对应的处理函数。
这就需要我们之前学到的多态(虚函数)了,可以直接将子类赋值给父类,而且在catch中是支持的。 (在c++异常机制(2)中说过了)
所以,我们可以将所有异常类都继承于一个父类,并且在父类中写一些处理异常所用的纯虚函数。(因为在父类中不需要实现,而且父类不需要定义对象,在子类中根据对应子类的需求对继承的纯虚函数进行实现)。
在使用虚函数之后,我们遇到异常之后,抛出对应异常类的匿名对象,然后再catch中使用父类型来捕获,这样接收的那个子类,然后就能调用对应子类的处理函数。
关于虚函数请看c++多态(2) -- 虚函数
代码:
#define BUFFER_SIZE 1024class FileError {
public:FileError(int err) :errorData(err) {};virtual void print() = 0; // 纯虚函数
protected: // 可以让元素在子类中直接使用int errorData;
};class OpenFileError : public FileError{
public:OpenFileError(int err) :FileError(err) {};void print() override{switch (errorData) {case -1:printf("源文件打开失败 %d\n", errorData);break;case -2:printf("目的文件打开失败 %d\n", errorData);break;}}
};class WriteFileError:public FileError{
public:WriteFileError(int err) :FileError(err) {}void print() override {printf("文件写入失败");}
};// 将一个文件中的内容拷贝到另外一个文件中去
int makeFile(const char* dest, const char* src) {// 定义文件指针FILE* fp1 = NULL, * fp2 = NULL;// 打开文件, 以只读二进制形式打开文件,打开失败返回NULLfp1 = fopen(src, "rb"); // 判断文件是否成功打开if (!fp1) {throw OpenFileError(-1);}// 打开文件,以只写二进制形式打开文件,打开失败返回NULLfp2 = fopen(dest, "wb");// 判断文件是否成功打开if (!fp2) {throw OpenFileError(-2); // 返回错误标记,表示目标文件打开失败}// 进行文件的拷贝char buffer[BUFFER_SIZE]; // 1024字节的缓存int readLen, writeLen; // 每次读取的长度和写入的长度// 读取的长度大于0,说明有内容可以写入,执行循环体的写入内容while ((readLen = fread(buffer, 1, BUFFER_SIZE, fp1)) > 0) {writeLen = fwrite(buffer, 1, readLen, fp2);// 如果一次写入的长度和读取的长度不等,那么说明写入失败if (readLen != writeLen) {throw WriteFileError(-1); }}// 关闭文件fclose(fp1);fclose(fp2);return 0; // 一切正常返回0
}int makeFile2(const char* dest, const char* src) {int ret;ret = makeFile(dest, src);printf("makeFile2 函数被调用");return ret;
}int main(void) {int ret = 0;try {ret = makeFile2("dest.txt", "src.txt");}catch (FileError& error) {error.print();}system("pause");return 0;
}
与前面的代码对比,catch的参数我们只需要写一个就可以匹配所有的异常情况,在异常类型多的情况下,这显然更加的简便。