版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
RTTI與異常處理8.1RTTI概述
RTTI(Run-TimeTypeIdentification,運行時類型識別),支持程序在運行時,根據(jù)基類指針或引用,確定其所指對象的實際類型。RTTI是RAD開發(fā)工具(如MFC)的基礎(chǔ)。在處理異類容器,以及在實現(xiàn)調(diào)試器程序時,都需要在運行時得知對象的類型,而虛函數(shù)機制不能滿足需求,那么如何確定對象的動態(tài)類型呢?C++為此提供的支持是內(nèi)建的RTTI運算符:dynamic_cast和typeid。8.1RTTI概述dynamic_cast運算符,支持程序在運行時,將基類指針安全轉(zhuǎn)換成派生類指針,或把指向基類的對象安全轉(zhuǎn)換成派生類的引用,所謂安全是指轉(zhuǎn)換成功后所得的指針或引用是一定可用的。typeid運算符,獲得指針或引用所指對象運行時的實際類型。8.2dynamic_cast運算符為什么需要dynamic_cast運算符?classEmployee{ //雇員類,基類public:
virtualintsalary();};classCaptain:publicEmployee{ //機長public: intsalary();};classStewardess:publicEmployee{ //空姐public: intsalary();};8.2dynamic_cast運算符另外有一個如下的計算薪水全局函數(shù)payroll():intpayroll(Employee*pe){
//使用pe->salary()}假設(shè)新需求是在payroll()的計算里,增加一項bonus,與salary()類似,不同類型員工的bonus()是不一樣的。為此,可以在Employee類中增加一個bonus()虛成員函數(shù),在計算payroll()時,bonus()與成員函數(shù)salary()一起被使用,例如:
8.2dynamic_cast運算符classEmployee{public:
virtualintsalary();
virtualintbonus(); //在基類中增加虛函數(shù)};classCaptain:publicEmployee{public: intsalary();};classStewardess:publicEmployee{public: intsalary(); intbonus();};intpayroll(Employee*pe){
//使用pe->salary()和pe->bonus()}8.2dynamic_cast運算符在類層次結(jié)構(gòu)中增加虛函數(shù)bonus(),缺點是需要有類Employee、Captain和Stewardess的實現(xiàn)源代碼,但如果上述的類層次結(jié)構(gòu)是由第三方庫提供的,沒有其實現(xiàn)源代碼,則無法采用增加基類虛成員函數(shù)方式。采用方法:可使用dynamic_cast,為用戶在不方便或者不想改變基類的情況下,模擬虛函數(shù)機制。具體做法:直接向派生類(如Stewardess類)中增加bonus()成員函數(shù)。8.2dynamic_cast運算符classEmployee{public:
virtualintsalary();};classCaptain:publicEmployee{public: intsalary();};classStewardess:publicEmployee{public: intsalary(); intbonus(); //在派生類中增加的非虛成員函數(shù)};8.2dynamic_cast運算符在函數(shù)payroll()中通過dynamic_cast運算符轉(zhuǎn)換得派生類Stewardess的指針,并用這個指針,調(diào)用其增加的非虛成員函數(shù)Stewardess::bonus():intpayroll(Employee*pe){Stewardess*pm=dynamic_cast<Stewardess*>(pe);if(pm){ //pm指向Stewardess對象
//用pm調(diào)用Stewardess::bonus()}else{ //dynamic_cast失敗,pm為0
//使用pe調(diào)用Employee的成員函數(shù)}}8.2dynamic_cast運算符注意:在使用結(jié)果指針之前,必須測試dynamic_cast是否轉(zhuǎn)換成功。例如:intpayroll(Employee*pe){Stewardess*pm=dynamic_cast<Stewardess*>(pe); staticintvariablePay=0;
//錯誤:在使用pm之前需要測試pm的值 variablePay+=pm->bonus();
//…}8.2dynamic_cast運算符【例8.1】dynamic_cast運算符使用示例。//employee.h#ifndefEMPLOYEE_H //防止employee.h被重復(fù)引用#defineEMPLOYEE_HclassEmployee{public:
virtualintsalary();};classCaptain:publicEmployee{public: intsalary();};classStewardess:publicEmployee{public: intsalary(); intbonus(); //增加的非虛成員函數(shù)};#endif8.2dynamic_cast運算符//employee.cpp#include"employee.h"intEmployee::salary(){
return0;}intCaptain::salary(){
return20000;}intStewardess::salary(){
return5000;}intStewardess::bonus(){
return2500;}8.2dynamic_cast運算符//mian.cpp#include"employee.h"#include<iostream>usingnamespacestd;intpayroll(Employee*pe){ //全局函數(shù)
Stewardess*pm=dynamic_cast<Stewardess*>(pe); if(pm){ //成功,返回派生類指針
//pe->salary()虛函數(shù)動態(tài)綁定
returnpm->bonus()+pe->salary();
//也可以通過pm靜態(tài)調(diào)用Stewardess類改寫后的虛函數(shù)pm->salary() //returnpm->bonus()+pm->salary(); } else{ //0
returnpe->salary(); }}8.2dynamic_cast運算符intmain(){Employee*e0=newCaptain();Employee*e1=newStewardess();cout<<payroll(e0)<<endl;cout<<payroll(e1)<<endl;
return0;}運行結(jié)果:2000075008.3typeid運算符typeid運算符的操作數(shù)可以是表達式或類型名,當(dāng)表達式是對象指針或引用時,可獲得運行時指針或引用所指對象的實際類型,返回一個類型為type_info的對象,type_info類在頭文件typeinfo中定義:classtype_info{private: type_info(consttype_info&); type_info&operator=(consttype_info&);public:
virtual~type_info(); intoperator==(consttype_info&)const; intoperator!=(consttype_info&)const; constchar*name()const;};8.3typeid運算符【例8.2】typeid運算符輸出操作數(shù)類型名示例。//main.cpp#include<typeinfo>#include<iostream>intmain(){ intiobj; std::cout<<typeid(iobj).name()<<std::endl; std::cout<<typeid(8.16).name()<<std::endl;
return0;}運行結(jié)果:intdouble8.3typeid運算符【例8.3】typeid運算符的操作數(shù)(基類)類型中沒有虛函數(shù)情況。//main.cpp#include<typeinfo>#include<iostream>classmyBase{/*沒有虛函數(shù)*/};classmyDerived:publicmyBase{/*沒有虛函數(shù)*/};intmain(){ myDeriveddobj; myBase*pb=&dobj; std::cout<<typeid(*pb).name()<<std::endl;//輸出:myBase return0;}運行結(jié)果:classmyBase8.3typeid運算符【例8.4】typeid運算符的操作數(shù)(基類)類型中有虛函數(shù)示例。//employee.h#ifndefEMPLOYEE_H //防止employee.h被重復(fù)引用#defineEMPLOYEE_HclassEmployee{public:
virtualintsalary(){return0;}};classCaptain:publicEmployee{};#endif8.3typeid運算符//main.cpp#include"employee.h"#include<typeinfo>#include<iostream>usingnamespacestd;intmain(){ Employee*pe=newCaptain; //輸出:"Captain" cout<<typeid(*pe).name()<<endl;
return0;}運行結(jié)果:classCaptain8.4
異常在程序運行時,往往會出現(xiàn)一些不可預(yù)期的錯誤,如除數(shù)為0、內(nèi)存申請失敗、類型轉(zhuǎn)換失敗,此時,希望能由正常的控制流程之外的代碼來處理,比如先釋放資源,而不是直接結(jié)束程序運行,為此,C++提供異常(exception)處理機制,在C++環(huán)境下編程,優(yōu)先采用的錯誤處理方式是異常。
首先,異常不會被忽略,如果用戶不捕捉(catch)程序中拋出的異常,默認行為是調(diào)用abort(),程序被終止(coredump)。其次,異常機制保證了當(dāng)異常被拋出時,try塊內(nèi)創(chuàng)建的自動變量被撤銷。8.5
異常的使用C++中異常有兩個部分:異常的拋出,以及異常的處理。當(dāng)程序出錯,C++通過throw表達式拋出異常;在異常出現(xiàn)之后,程序的正常執(zhí)行被暫停,異常處理機制開始搜尋程序中有能力處理這一異常的catch子句,在異常處理完畢之后,程序從異常處理地點繼續(xù)向下執(zhí)行。8.5
異常的使用1.拋出異常voidfoo()throw(exception_1,exception_n){ if(error_1(…)){ //…
throwexception_1; //1 } … if(error_n(…)){ //…
throwexception_n; }}8.5
異常的使用其中,exception_1、exception_n是程序出錯時拋出的異常,異常是某種對象,最簡單的異常對象可以是一個整數(shù)或者字符串,如:throw32;throw"helloexception";8.5
異常的使用2.處理異常voidbar(){
try
{ foo(); //2 }
catch(exception_1e1){ //3 handle_exception_1(e1); }
catch(exception_nen){ handle_exception_n(en); }}函數(shù)在一旦拋出異常后就自動終止運行,將運行的權(quán)限交給它的上一層調(diào)用方。8.5
異常的使用3.trytry塊中的語句是可能拋出異常的地方。try總是與catch一同出現(xiàn),try把一組catch子句與try塊內(nèi)的函數(shù)體關(guān)聯(lián)起來,對于一個try塊,至少應(yīng)該有一個catch()子句,如果函數(shù)體中的語句拋出了一個異常,則使用函數(shù)體后面catch子句來處理這個異常。8.5
異常的使用4.catch在程序中,利用一個或者一串catch子句來捕捉(catch)被拋出的異常對象,catch子句由3部分組成:關(guān)鍵字catch、圓括號內(nèi)的一個類型或者對象、花括號內(nèi)的一組語句(用于處理異常),如上例中:catch(exception_nen){ handle_exception(en);}8.5
異常的使用如下為T類型的對象定義一個catch子句(變量t是任意的,與函數(shù)形參類似):catch(Tt)catch(constTt)catch(T&t)catch(constT&t)編譯器按照catch出現(xiàn)的順序以及catch指定的參數(shù)類型,確定一個異常應(yīng)該由哪個catch來處理。異常對象會被用來依次和每個catch子句比較類型,如果類型相符,則該catch子句的內(nèi)容便會執(zhí)行。
8.5
異常的使用catch不一定要全部捕捉try塊中拋出的異常,剩下沒有捕捉的可以交給上一級函數(shù)處理。在程序中,可以使用一網(wǎng)打盡(catch-all)的方式,使用(…)作為catch的參數(shù),支持捕捉任意類型的異常,示例如下:catch(…){ //捕捉任何類型的異常
log_message(); //處理異常}8.5
異常的使用有時,catch子句可能無法完成異常的完整處理,在處理之后,程序可以重拋異常,以尋求其它catch子句的協(xié)助,作進一步的處理:catch(iterator_overflow&iof){ log_message(iof.what_happened());
throw;//重拋異常,使另一個catch子句可以繼續(xù)處理}重拋時,只需在catch子句中寫下throw,throw會將捕捉的異常對象再次拋出,并由另一個類型吻合的catch子句繼續(xù)處理。8.5
異常的使用5.throwthrow后面帶一個類型的實例,throw和catch的關(guān)系就像是函數(shù)調(diào)用,catch指定形參,throw給出實參。throw不一定非要出現(xiàn)在try之后的語句塊中,它可以出現(xiàn)在任何需要的地方,只要最終有catch可以捕捉它即可,即使在catch子句中,仍然可以繼續(xù)throw,這時有兩種情況:重拋異常,重拋異常時throw不帶參數(shù)。throw一個新類型的異常。8.5
異常的使用try{ …}catch(int){
//拋出一個MyException類型的異常
throwMyException("myexception"); }catch(float){
throw; //重新拋出當(dāng)前的浮點數(shù)類型異常}8.5
異常的使用在函數(shù)聲明后的throw關(guān)鍵字稱為異常規(guī)范,通過異常規(guī)范,在函數(shù)聲明中,可以指定該函數(shù)能夠直接或間接拋出的異常集合(可不拋出任何異常),異常規(guī)范保證函數(shù)不會拋出未列出的異常,例如:voidfoo()throw(int); //只能拋出int型異常voidbar()throw();
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度瓦工裝修綠色施工認證合同3篇
- 二零二五版?;饭愤\輸安全監(jiān)管服務(wù)合同2篇
- 二零二五版攪拌站輪胎專用備品備件供應(yīng)合同3篇
- 二零二五版智能辦公樓深度清潔及保養(yǎng)服務(wù)合同2篇
- 二零二五版辦公室文員工作環(huán)境優(yōu)化合同3篇
- 二零二五年度高端房地產(chǎn)項目個人連帶責(zé)任保證擔(dān)保合同2篇
- 二零二五年度互聯(lián)網(wǎng)數(shù)據(jù)中心(IDC)設(shè)施租賃合同3篇
- 2025年度中式烹飪技藝傳承與創(chuàng)新合同協(xié)議3篇
- 屋頂防水施工合同(2篇)
- 二零二五年救生員水上安全培訓(xùn)與勞動合同3篇
- 廣東省惠州市2024-2025學(xué)年高一上學(xué)期期末考試英語試題(含答案)
- 醫(yī)院骨科2025年帶教計劃(2篇)
- 環(huán)境保護應(yīng)急管理制度執(zhí)行細則
- 2024-2030年中國通航飛行服務(wù)站(FSS)行業(yè)發(fā)展模式規(guī)劃分析報告
- 機械制造企業(yè)風(fēng)險分級管控手冊
- 地系梁工程施工方案
- 藏文基礎(chǔ)-教你輕輕松松學(xué)藏語(西藏大學(xué))知到智慧樹章節(jié)答案
- 2024電子商務(wù)平臺用戶隱私保護協(xié)議3篇
- 安徽省蕪湖市2023-2024學(xué)年高一上學(xué)期期末考試 英語 含答案
- 醫(yī)學(xué)教程 常見體表腫瘤與腫塊課件
- 內(nèi)分泌系統(tǒng)異常與虛勞病關(guān)系
評論
0/150
提交評論