我們在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的參數我們只需要寫一個就可以匹配所有的異常情況,在異常類型多的情況下,這顯然更加的簡便。?
?