throw關鍵字用來拋出一個異常,這個異常會被 try 檢測到,進而被 catch 捕獲。
異常既然是一份數據,那么就應該有數據類型。C++ 規定,異常類型可以是 int、char、float、bool 等基本類型,也可以是指針、數組、字符串、結構體、類等聚合類型。C++ 語言本身以及標準庫中的函數拋出的異常,都是 exception 類或其子類的異常。也就是說,拋出異常時,會創建一個 exception 類或其子類的對象。
可以將 catch 看做一個沒有返回值的函數,當異常發生后 catch 會被調用,并且會接收實參(異常數據)。
但是 catch 和真正的函數調用又有區別:
真正的函數調用,形參和實參的類型必須要匹配,或者可以自動轉換,否則在編譯階段就報錯了。
而對于 catch,異常是在運行階段產生的,它可以是任何類型,沒法提前預測,所以不能在編譯階段判斷類型是否正確,只能等到程序運行后,真的拋出異常了,再將異常類型和 catch 能處理的類型進行匹配,匹配成功的話就“調用”當前的 catch,否則就忽略當前的 catch。
#include <windows.h>
#include "resource.h"LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);HINSTANCE hInst;
TCHAR szClassName[] = TEXT("expDemo");class Base{ };
class Derived: public Base{ };int WINAPI
WinMain (HINSTANCE hThisInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nFunsterStil)
{HWND hwnd;MSG messages;WNDCLASSEX wincl;hInst = hThisInstance;wincl.hInstance = hThisInstance;wincl.lpszClassName = szClassName;wincl.lpfnWndProc = WindowProcedure;wincl.style = CS_DBLCLKS;wincl.cbSize = sizeof (WNDCLASSEX);wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);wincl.hCursor = LoadCursor (NULL, IDC_ARROW);wincl.lpszMenuName = MAKEINTRESOURCE (IDC_EXPDEMO);wincl.cbClsExtra = 0;wincl.cbWndExtra = 0;wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);if (!RegisterClassEx (&wincl))return 0;hwnd = CreateWindowEx (0,szClassName,TEXT("C++異常處理Demo"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,300,300,HWND_DESKTOP,NULL,hThisInstance,NULL);ShowWindow (hwnd, nFunsterStil);while (GetMessage (&messages, NULL, 0, 0)){TranslateMessage(&messages);DispatchMessage(&messages);}return messages.wParam;
}LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{PAINTSTRUCT ps;HDC hdc;RECT rt; char szBuffer[100]; switch (message){case WM_COMMAND:switch (LOWORD(wParam)){case IDM_exp: hdc=GetDC(hwnd);try{throw Derived();wsprintf(szBuffer, "%s","This statement will not be executed.");TextOut(hdc,100,10,szBuffer,lstrlen(szBuffer));}catch(int){wsprintf(szBuffer, "%s","Exception type: int");TextOut(hdc,100,40,szBuffer,lstrlen(szBuffer));}catch(char *){wsprintf(szBuffer, "%s","Exception type: cahr *");TextOut(hdc,100,70,szBuffer,lstrlen(szBuffer));}catch(Base){wsprintf(szBuffer, "%s","Exception type: Base");TextOut(hdc,100,100,szBuffer,lstrlen(szBuffer));}catch(Derived){wsprintf(szBuffer, "%s","Exception type: Derived");TextOut(hdc,100,130,szBuffer,lstrlen(szBuffer));}break;case IDM_ABOUT:MessageBox (hwnd, TEXT ("expDemo v1.0\nCopyright (C) 2020\n by bo"),TEXT ("expDemo"), MB_OK | MB_ICONINFORMATION);break;case IDM_EXIT:DestroyWindow(hwnd);break;default:return DefWindowProc(hwnd, message, wParam, lParam); }break;case WM_CREATE:break;case WM_PAINT:hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rt); EndPaint(hwnd, &ps);break;case WM_DESTROY:PostQuitMessage (0);break;default:return DefWindowProc (hwnd, message, wParam, lParam);}return 0;
}
運行;
?
定義了一個基類 Base,又從 Base 派生類出了 Derived。拋出異常時,創建了一個 Derived 類的匿名對象,也就是說,異常的類型是 Derived。
期望的是,異常被catch(Derived)捕獲,從輸出結果可以看出,異常提前被catch(Base)捕獲了,這說明 catch 在匹配異常類型時發生了向上轉型(Upcasting)。
參閱:
http://c.biancheng.net/view/2330.html
工程;
資源文件,頭文件;
#include "resource.h"
#include <windows.h>/
//
// Menu
//IDC_EXPDEMO MENU
BEGINPOPUP "&File"BEGINMENUITEM "C++異常處理Demo", IDM_expMENUITEM "E&xit", IDM_EXITENDPOPUP "&Help"BEGINMENUITEM "&About ...", IDM_ABOUTEND
END
#define IDM_EXIT 10001
#define IDM_ABOUT 10002#define IDC_EXPDEMO 10101
#define IDD_ABOUTBOX 10102
#define IDM_exp 40001
?
總結
以上是生活随笔為你收集整理的C++ 异常处理Demo - win32 版的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。