日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++ throw

發(fā)布時(shí)間:2025/3/12 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ throw 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我們知道C++ 異常處理的流程,具體為:

拋出(Throw)--> 檢測(cè)(Try) --> 捕獲(Catch)

異常必須顯式地拋出,才能被檢測(cè)和捕獲到;如果沒(méi)有顯式的拋出,即使有異常也檢測(cè)不到。

在 C++ 中,我們使用 throw 關(guān)鍵字來(lái)顯式地拋出異常,它的用法為:

throw exceptionData;

exceptionData 是“異常數(shù)據(jù)”的意思,它可以包含任意的信息,完全有程序員決定。exceptionData 可以是 int、float、bool 等基本類型,也可以是指針、數(shù)組、字符串、結(jié)構(gòu)體、類等聚合類型,請(qǐng)看下面的例子:

char str[] = "http://c.biancheng.net"; char *pstr = str;class Base{}; Base obj;throw 100; //int 類型 throw str; //數(shù)組類型 throw pstr; //指針類型 throw obj; //對(duì)象類型

一個(gè)動(dòng)態(tài)數(shù)組的例子

C/C++ 規(guī)定,數(shù)組一旦定義后,它的長(zhǎng)度就不能改變了;換句話說(shuō),數(shù)組容量不能動(dòng)態(tài)地增大或者減小。這樣的數(shù)組稱為靜態(tài)數(shù)組(Static array)。靜態(tài)數(shù)組有時(shí)候會(huì)給編碼代碼不便,我們可以通過(guò)自定義的 Array 類來(lái)實(shí)現(xiàn)動(dòng)態(tài)數(shù)組(Dynamic array)。所謂動(dòng)態(tài)數(shù)組,是指數(shù)組容量能夠在使用的過(guò)程中隨時(shí)增大或減小。

使用異常示例。

#include <iostream> #include <cstdlib> using namespace std;//自定義的異常類型 class OutOfRange{ public:OutOfRange(): m_flag(1){ };OutOfRange(int len, int index): m_len(len), m_index(index), m_flag(2){ } public:void what() const; //獲取具體的錯(cuò)誤信息 private:int m_flag; //不同的flag表示不同的錯(cuò)誤int m_len; //當(dāng)前數(shù)組的長(zhǎng)度int m_index; //當(dāng)前使用的數(shù)組下標(biāo) };void OutOfRange::what() const {if(m_flag == 1){cout<<"Error: empty array, no elements to pop."<<endl;}else if(m_flag == 2){cout<<"Error: out of range( array length "<<m_len<<", access index "<<m_index<<" )"<<endl;}else{cout<<"Unknown exception."<<endl;} }//實(shí)現(xiàn)動(dòng)態(tài)數(shù)組 class Array{ public:Array();~Array(){ free(m_p); }; public:int operator[](int i) const; //獲取數(shù)組元素int push(int ele); //在末尾插入數(shù)組元素int pop(); //在末尾刪除數(shù)組元素int length() const{ return m_len; }; //獲取數(shù)組長(zhǎng)度 private:int m_len; //數(shù)組長(zhǎng)度int m_capacity; //當(dāng)前的內(nèi)存能容納多少個(gè)元素int *m_p; //內(nèi)存指針 private:static const int m_stepSize = 50; //每次擴(kuò)容的步長(zhǎng) };Array::Array(){m_p = (int*)malloc( sizeof(int) * m_stepSize );m_capacity = m_stepSize;m_len = 0; } int Array::operator[](int index) const {if( index<0 || index>=m_len ){ //判斷是否越界throw OutOfRange(m_len, index); //拋出異常(創(chuàng)建一個(gè)匿名對(duì)象)}return *(m_p + index); } int Array::push(int ele){if(m_len >= m_capacity){ //如果容量不足就擴(kuò)容m_capacity += m_stepSize;m_p = (int*)realloc( m_p, sizeof(int) * m_capacity ); //擴(kuò)容}*(m_p + m_len) = ele;m_len++;return m_len-1; } int Array::pop(){if(m_len == 0){throw OutOfRange(); //拋出異常(創(chuàng)建一個(gè)匿名對(duì)象)}m_len--;return *(m_p + m_len); }//打印數(shù)組元素 void printArray(Array &arr){int len = arr.length();//判斷數(shù)組是否為空if(len == 0){cout<<"Empty array! No elements to print."<<endl;return;}for(int i=0; i<len; i++){if(i == len-1){cout<<arr[i]<<endl;}else{cout<<arr[i]<<", ";}} }int main(){Array nums;//向數(shù)組中添加十個(gè)元素for(int i=0; i<10; i++){nums.push(i);}printArray(nums);//嘗試訪問(wèn)第20個(gè)元素try{cout<<nums[20]<<endl;}catch(OutOfRange &e){e.what();}//嘗試彈出20個(gè)元素try{for(int i=0; i<20; i++){nums.pop();}}catch(OutOfRange &e){e.what();}printArray(nums);return 0; }

運(yùn)行結(jié)果:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 Error: out of range( array length 10, access index 20 ) Error: empty array, no elements to pop. Empty array! No elements to print.

Array 類實(shí)現(xiàn)了動(dòng)態(tài)數(shù)組,它的主要思路是:在創(chuàng)建對(duì)象時(shí)預(yù)先分配出一定長(zhǎng)度的內(nèi)存(通過(guò) malloc() 分配),內(nèi)存不夠用時(shí)就再擴(kuò)展內(nèi)存(通過(guò) realloc() 重新分配)。Array 數(shù)組只能在尾部一個(gè)一個(gè)地插入(通過(guò) push() 插入)或刪除(通過(guò) pop() 刪除)元素。

我們通過(guò)重載過(guò)的[ ]運(yùn)算符來(lái)訪問(wèn)數(shù)組元素,如果下標(biāo)過(guò)小或過(guò)大,就會(huì)拋出異常(第53行代碼);在拋出異常的同時(shí),我們還記錄了當(dāng)前數(shù)組的長(zhǎng)度和要訪問(wèn)的下標(biāo)。

在使用 pop() 刪除數(shù)組元素時(shí),如果當(dāng)前數(shù)組為空,也會(huì)拋出錯(cuò)誤。

throw 用作異常規(guī)范

throw 關(guān)鍵字除了可以用在函數(shù)體中拋出異常,還可以用在函數(shù)頭和函數(shù)體之間,指明當(dāng)前函數(shù)能夠拋出的異常類型,這稱為異常規(guī)范(Exception specification)。

double func (char param) throw (int);

這條語(yǔ)句聲明了一個(gè)名為 func 的函數(shù),它的返回值類型為 double,有一個(gè) char 類型的參數(shù),并且只能拋出 int 類型的異常。如果拋出其他類型的異常,try 將無(wú)法捕獲,只能終止程序。

如果函數(shù)會(huì)拋出多種類型的異常,那么可以用逗號(hào)隔開(kāi):

double func (char param) throw (int, char, exception);

如果函數(shù)不會(huì)拋出任何異常,那么( )中什么也不寫:

double func (char param) throw ();

如此,func() 函數(shù)就不能拋出任何類型的異常了,即使拋出了,try 也檢測(cè)不到。

1 虛函數(shù)中的異常規(guī)范
C++ 規(guī)定,派生類虛函數(shù)的異常規(guī)范必須與基類虛函數(shù)的異常規(guī)范一樣嚴(yán)格,或者更嚴(yán)格。只有這樣,當(dāng)通過(guò)基類指針(或者引用)調(diào)用派生類虛函數(shù)時(shí),才能保證不違背基類成員函數(shù)的異常規(guī)范。請(qǐng)看下面的例子:

class Base{ public:virtual int fun1(int) throw();virtual int fun2(int) throw(int);virtual string fun3() throw(int, string); }; class Derived:public Base{ public:int fun1(int) throw(int); //錯(cuò)!異常規(guī)范不如 throw() 嚴(yán)格int fun2(int) throw(int); //對(duì)!有相同的異常規(guī)范string fun3() throw(string); //對(duì)!異常規(guī)范比 throw(int,string) 更嚴(yán)格 }

2 異常規(guī)范與函數(shù)定義和函數(shù)聲明
C++ 規(guī)定,異常規(guī)范在函數(shù)聲明和函數(shù)定義中必須同時(shí)指明,并且要嚴(yán)格保持一致,不能更加嚴(yán)格或者更加寬松。

請(qǐng)看下面的幾組函數(shù):

//錯(cuò)!定義中有異常規(guī)范,聲明中沒(méi)有 void func1(); void func1() throw(int) { }//錯(cuò)!定義和聲明中的異常規(guī)范不一致 void func2() throw(int); void func2() throw(int, bool) { }//對(duì)!定義和聲明中的異常規(guī)范嚴(yán)格一致 void func3() throw(float, char*); void func3() throw(float, char*) { }

拋棄異常規(guī)范

異常規(guī)范的初衷是好的,它希望讓程序員看到函數(shù)的定義或聲明后,立馬就知道該函數(shù)會(huì)拋出什么類型的異常,這樣程序員就可以使用 try-catch 來(lái)捕獲了。如果沒(méi)有異常規(guī)范,程序員必須閱讀函數(shù)源碼才能知道函數(shù)會(huì)拋出什么異常。

不過(guò)這有時(shí)候也不容易做到。例如,func_outer() 函數(shù)可能不會(huì)引發(fā)異常,但它調(diào)用了另外一個(gè)函數(shù) func_inner(),這個(gè)函數(shù)可能會(huì)引發(fā)異常。再如,您編寫的函數(shù)調(diào)用了老式的庫(kù)函數(shù),此時(shí)不會(huì)引發(fā)異常,但是庫(kù)更新以后這個(gè)函數(shù)卻引發(fā)了異常。總之,異常規(guī)范的初衷實(shí)現(xiàn)起來(lái)有點(diǎn)困難,所以大家達(dá)成的一致意見(jiàn)是,最好不要使用異常規(guī)范。

異常規(guī)范是 C++98 新增的一項(xiàng)功能,但是后來(lái)的 C++11 已經(jīng)將它拋棄了,不再建議使用。

另外,各個(gè)編譯器對(duì)異常規(guī)范的支持也不一樣,請(qǐng)看下面的代碼:

#include <iostream> #include <string> #include <exception> using namespace std;void func()throw(char*, exception){throw 100;cout<<"[1]This statement will not be executed."<<endl; }int main(){try{func();}catch(int){cout<<"Exception type: int"<<endl;}return 0; }

在 GCC 下,這段代碼運(yùn)行到第 7 行時(shí)程序會(huì)崩潰。雖然 func() 函數(shù)中發(fā)生了異常,但是由于 throw 限制了函數(shù)只能拋出 char*、exception 類型的異常,所以 try-catch 將捕獲不到異常,只能交給系統(tǒng)處理,終止程序。

在 Visual C++ 下,輸出結(jié)果為Exception type: int,這說(shuō)明異常被成功捕獲了。在 Visual C++ 中使用異常規(guī)范雖然沒(méi)有語(yǔ)法錯(cuò)誤,但是也沒(méi)有任何效果,Visual C++ 會(huì)直接忽略異常規(guī)范的限制,函數(shù)可以拋出任何類型的異常。

總結(jié)

以上是生活随笔為你收集整理的C++ throw的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。