13、C++異常處理

13、c++異常處理

  • 拋出異常
  • 捕獲異常
  • 未拋出異常時的流程
  • 拋出異常時的流程
  • 捕獲異常
  • 匹配順序
  • 異常說明
  • 異常處理
  • 構造函數中的異常
  • 析構函數中的異常
  • 標準庫異常類

拋出異常

  • throw 異常對象
  • 可以拋出基本類型的對象,如:throw -1;throw "內存分配失敗!";
  • 也可以拋出類類型的對象,如:MemoryException ex;throw ex;throw MemoryException();
  • 但不要拋出局部對象的指針,如:MemoryException ex;throw &ex; // 錯誤!

捕獲異常

try {
可能引發異常的語句
}
catch (異常類型1& ex){針對異常類型1的異常處理;}
catch (異常類型2& ex) {針對異常類型2的異常處理;}
...
catch (異常類型n& ex) {針對異常類型n的異常處理;}

未拋出異常時的流程

在這里插入圖片描述

拋出異常時的流程

在這里插入圖片描述

捕獲異常

  • 建議在catch子句中使用引用接收異常對象,避免因為拷貝構造帶來性能損失
  • 推薦以匿名臨時對象的形式拋出異常
  • 異常對象必須允許被拷貝構造和析構

匹配順序

根據異常對象的類型自上至下順序匹配,而非最優匹配,因此對子類類型異常的捕獲不要放在對基類類型異常的捕獲后面

異常說明

異常說明是函數原型的一部分,旨在說明函數可能拋出的異常類型
返回類型 函數名(形參表) throw (異常類型1,異常類型2,...) {函數體;}

異常說明是一種承諾,承諾函數不會拋出異常說明以外的異常類型
如果函數拋出了異常說明以外的異常類型,那么該異常將無法被捕獲并導致進程中止

隱式拋出異常的函數也可以列出它的異常說明

異常說明可以沒有也可以為空

  • 沒有異常說明,表示可能拋出任何類型的異常
    • void foo (void) { ... }
  • 異常說明為空,表示不會拋出任何類型的異常
    • void foo (void) throw () { ... }

異常說明在函數的聲明和定義中必須保持嚴格一致,否則將導致編譯錯誤

異常處理

  • 可以拋出基本類型的異常
  • 可以拋出類類型的異常
  • 利用類類型的異常,攜帶更多診斷信息,以便查錯
  • 可以在catch塊中繼續拋出所捕獲的異常,或其它異常
  • 任何未被捕獲的異常,默認的處理方式就是中止進程
  • 忽略異常,不做處理

構造函數中的異常

構造函數可以拋出異常,某些時候還必須拋出異常

  • 構造過程中可能遇到各種錯誤,比如內存分配失敗
  • 構造函數沒有返回值,無法通過返回值通知調用者

構造函數拋出異常,對象將被不完整構造,而一個被不完整構造的對象,其析構函數永遠不會被執行

  • 所有對象形式的成員變量,在拋出異常的瞬間,都能得到正確地析構 (構造函數的回滾機制)
  • 所有動態分配的資源,必須在拋出異常之前,自己手動釋放,否則將形成資源的泄漏

析構函數中的異常

不要從析構函數中主動拋出異常

在兩種情況下,析構函數會被調用

  • 正常銷毀對象,離開作用域或顯式delete
  • 在異常傳遞的堆棧輾轉開解(stack-unwinding)過程中

對于第二種情況,異常正處于激活狀態,而析構函數又拋出了異常這時C++將通過std::terminate()函數,令進程中止
對于可能引發異常的操作,盡量在析構函數內部消化
try {... }catch (...) { ... }

標準庫異常類

在這里插入圖片描述

// 利用return報告異常信息
#include <iostream>
#include <cstdio>
using namespace std;class A{
public:A() {  cout << "A()被調用" << endl; }~A(){  cout << "~A()被調用" << endl; }
};void foo(){cout << "foo出錯前的幾百行代碼" << endl;A a;FILE* pfile = fopen("./cfg","r");if(!pfile)throw -1;cout << "foo出錯后的幾百行代碼" << endl;
} // a.~A() 釋放a本身所占內存空間void bar(){cout << "bar出錯前的幾百行代碼" << endl;A b;
//    try{foo();
//    }
//    catch(int e){
//        cout << "bar函數中捕獲異常信息: " << e << endl;
//    }cout << "bar出錯后的幾百行代碼" << endl;
} // b.~A() 釋放b本身所占內存空間void hum(){cout << "hum出錯前的幾百行代碼" << endl;A c;try{bar();}catch(int e){cout << "hum函數中捕獲異常信息:" << e << endl;}cout << "bar出錯后的幾百行代碼" << endl;
} // c.~A() 釋放c本身所占內存空間int main( void ){cout << "main出錯前的幾百行代碼" << endl;A d;hum();cout << "main出錯后的幾百行代碼" << endl;return 0;
} // d.~A() 釋放d本身所占內存空間
// 建議將子類類型異常捕獲放到基類類型異常捕獲的前面
#include <iostream>
using namespace std;class A{};class B : public A{};void foo(){throw B();
}int main( void ){try{foo();}catch(B& b){  cout << "B類型catch捕獲" << endl;}catch(A& a){  cout << "A類型catch捕獲" << endl;}return 0;
} 
// 沒有異常說明和異常說明為空
#include <iostream>
using namespace std;void foo()  { // 沒有異常說明:函數內部可能拋出任何類型的異常throw  "Hello world!"; // 3.14; // -1;
}void bar() throw(){ // 異常說明為空:承諾函數內部絕對不會拋出任何類型的異常
//  throw -1;
}
// 異常說明在聲明和定義時必須嚴格一致,否則將報編譯錯誤
void hum() throw(int,double);  // 聲明
void hum() throw(int,double){ // 定義
}int main( void ){try{foo();
//     bar();}catch( ... ){ // 忽略異常// ...}/*    catch(int& e){cout << "1. 捕獲異常信息:"<< e << endl; }catch(double& e){cout << "2. 捕獲異常信息:" << e << endl;}catch(const char* e){cout << "3. 捕獲異常信息:" << e << endl;}*/return 0;
} 
// 構造函數中的異常
#include <iostream>
#include <cstdio>
using namespace std;class A{
public:A(){ cout << "A()被調用" << endl; }~A(){ cout << "~A()被調用" << endl; }
};
class C{
public:C():m_p(new int){//【A m_a;】定義m_a,利用m_a.A()//【int* m_p = new int;】定義m_p,初值指向一塊堆內存(動態資源)cout << "C()被調用" << endl;FILE* pfile = fopen("./cfg","r");if(!pfile){delete m_p; // 需要自己手動釋放// 對于m_a.利用m_a.~A()// 釋放m_a/m_p本身所占內存空間throw -1;}// ....構造函數中后續代碼...}~C(){delete m_p;cout << "~C()被調用" << endl;// 對于m_a.利用m_a.~A()// 釋放m_a/m_p本身所占內存空間}
private:A m_a;int* m_p;
};int main( void ){try{C c; // 定義c,利用c.C();}// 如果c是完整構造對象,將利用c.~C(),但是如果c是殘缺對象,就不會調用~C()catch( ... ){// ...}return 0;
} 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213601.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213601.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213601.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AVP對縱向控制ESP(Ibooster)的需求規范

目錄 1. 版本記錄... 3 2. 文檔范圍和控制... 4 2.1 目的/范圍... 4 2.2 文檔沖突... 4 2.3 文檔授權... 4 2.4 文檔更改控制... 4 3. 功能概述... 5 4. 系統架構... 6 5. 主要安全目標... 7 5.1 …

FreeSSL申請免費域名證書

本文詳細講解如何申請免費證書&#xff0c;需要先準備好域名&#xff0c;將服務器IP和域名綁定。 1、注冊FreeSSL賬號 網址&#xff1a; https://freessl.org/ 2、申請流程 登錄后首頁輸入域名&#xff0c;然后點擊Create certificate&#xff0c;跳轉到證書申請頁面。 或者…

Pytorch深度強化學習1-6:詳解時序差分強化學習(SARSA、Q-Learning算法)

目錄 0 專欄介紹1 時序差分強化學習2 策略評估原理3 策略改進原理3.1 SARSA算法3.2 Q-Learning算法 0 專欄介紹 本專欄重點介紹強化學習技術的數學原理&#xff0c;并且采用Pytorch框架對常見的強化學習算法、案例進行實現&#xff0c;幫助讀者理解并快速上手開發。同時&#…

老人的數目

給你一個下標從 0 開始的字符串 details 。details 中每個元素都是一位乘客的信息&#xff0c;信息用長度為 15 的字符串表示&#xff0c;表示方式如下&#xff1a; 前十個字符是乘客的手機號碼。接下來的一個字符是乘客的性別。接下來兩個字符是乘客的年齡。最后兩個字符是乘…

QGIS 加載在線XYZ地圖圖層

QGIS 加載在線XYZ地圖圖層 定義并添加必應XYZ圖層 Go to Layer > Add Layer > Add XYZ Layer…Click NewName as BingMaps(as you wish)URL as http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g1click OkSelect XYZ Connections as Bing Maps(Which you creat…

PR自動剪輯視頻工具AI智能剪輯插件AutoPod

推薦一款可以提高剪輯效率&#xff0c;節約時間成本的AI人工智能自動剪輯視頻制作工具pr插件Autopod&#xff0c;輔助你更快地完成視頻內容的編輯工作。 Autopod 插件是一款應用于 Adobe Premiere Pro 軟件的插件&#xff0c;用于自動剪輯。該插件能夠識別和處理視頻和音頻素材…

Spring Boot 常用注解分類

目錄 1.核心注解&#xff1a;2.配置相關注解&#xff1a;3.控制器相關注解&#xff1a;4.數據訪問相關注解&#xff1a;5.測試相關注解&#xff1a;6.條件注解&#xff1a;7.AOP相關注解&#xff1a;8.定時任務相關注解&#xff1a;9.消息隊列相關注解&#xff1a;10.Spring Se…

函數式編程解析:定義、功能與Java實踐

目錄 一、函數式編程1.1 什么是函數式編程1.2 函數式編程特征1.2.1 純函數1.2.2 函數是一等公民 1.3 函數式編程在java中的實踐 參考資料 一、函數式編程 1.1 什么是函數式編程 函數式編程&#xff08;Functional Programming&#xff09;是一種編程范式&#xff0c;它將計算…

ES6中的迭代器和set、map集合

什么是迭代器&#xff1f; 一種機制&#xff0c;也是一種接口&#xff0c;為數據結構提供統一訪問接口&#xff0c;依次處理數據據結構成員 只要實現了迭代器接口&#xff0c;就可以使用for...of循環遍歷。 /*** 迭代器是一種機制 是一種接口 只要數據解構實現了接口 就可…

力扣labuladong一刷day36天

力扣labuladong一刷day36天 一、96. 不同的二叉搜索樹 題目鏈接&#xff1a;https://leetcode.cn/problems/unique-binary-search-trees/ 思路&#xff1a;這是一道典型的動態規劃題&#xff0c;從n3來看 子樹有幾種形態 (0, 2)、(1, 1)、(2, 0)有規律可循&#xff0c;即為左…

飛天使-linux操作的一些技巧與知識點4

文章目錄 ansible配置文件的優先級嘗試開始進行操作ansible常用模塊ansible 的playbook示例安裝phpplaybook中變量的引用 ansible yum install -y ansible 測試是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg &#xff1a;主配置文件&#xff0c;配置 ansible…

大公司求我用Kotlin寫個通用爬蟲模板

bug虐我千百遍&#xff0c;我待他如初戀。每次深夜挑燈都是我與bug較量的時間。今天我要說的就是寫一個爬蟲模版&#xff0c;自動抓取百度圖片的教程&#xff0c;這次使用Kotlin編寫的爬蟲程序在Scrapy框架下完成的&#xff0c;如有不足歡迎指正。 首先&#xff0c;使用Kotlin編…

Mybatis-Plus源碼解析之@MapperScan(一)

group : com.baomidou version:3.5.2.2-SNAPSHOT baomidou官網可以從快速開始了解到&#xff0c;除了配置數據源&#xff0c;最重要的就是MapperScan 注解&#xff0c;在 Spring Boot 啟動類中添加 MapperScan 注解&#xff0c;掃描 Mapper 文件夾。 MapperScan 按照慣例&…

angular form 組件、雙向綁定;反應式表單

1.使用雙向綁定&#xff0c;以及angular的表單提交功能 app.moudle中引入 雙向綁定 [(ngModel)]"text" ??????? 效果 提交表單 2.反應式表單 在app.module.ts中引入在組件中引入&#xff0c;并放在一個變量里 在初始化時實列化這個module 定義規則 在html…

Linux:環境變量

目錄 1.基本變量 2.通過代碼獲取環境變量 2.1 main傳參 2.2 全局變量environ 2.3 系統調用getenv() 3.在腳本文件中添加環境變量 4.環境變量通常是具有全局屬性 1.基本變量 環境變量(environment variables)一般是指在操作系統中用來指定操作系統運行環境的一些參數…

商用中央空調市場分析:預計2028年將達到628億元

商用空調一直以來都沒有一個相對比較明確的概念&#xff0c;一直以來被認為是制冷空調市場的一個細分子行業。現在比較一致的觀點是&#xff0c;可以納入商用空調范疇的產品可以包括戶式中央空調產品、部分傳統中央空調產品以及部分家用空調。商用空調已普遍采用直流變頻領先技…

網絡計算機模擬實現

今天給大家說說前幾天完成的一個模擬的網絡計算機吧&#xff0c;雖然計算機的模擬實現的原理很簡單&#xff0c;但是如果要想寫乘網絡的&#xff0c;個人認為是不簡單的。基本上算是包涵了套接字編程的三分之一的知識點&#xff0c;此處的套接字編程指的是在理解TCP/IP五層協議…

泡沫玻璃市場分析:預計2028年將達到14億美元

泡沫玻璃最早是由美國匹茲堡康寧公司發明的&#xff0c;是由碎玻璃、發泡劑、改性添加劑和發泡促進劑等&#xff0c;經過細粉碎和均勻混合后&#xff0c;再經過高溫熔化&#xff0c;發泡、退火而制成的無機非金屬玻璃材料。它是由大量直徑為1~2毫米的均勻氣泡結構組成。其中吸聲…

Linux 常用命令----mktemp 命令

文章目錄 基本用法實例演示高級用法注意事項 mktemp 命令用于創建一個臨時文件或目錄&#xff0c;這在需要處理臨時數據或進行安全性測試時非常有用。使用 mktemp 可以保證文件名的唯一性&#xff0c;避免因文件名沖突而導致的問題。 基本用法 創建臨時文件: 命令 mktemp 默認…

Go語言基礎知識學習(一)

Go基本數據類型 bool bool型值可以為true或者false,例子&#xff1a; var b bool true數值型 類型表示范圍int8有符號8位整型-128 ~ 127int16有符號16位整型-32768 ~ 32767int32有符號32位整型-2147783648 ~ 2147483647int64有符號64位整型uint8無符號8位整型0 ~ 255uint16…