上兩篇文章分別詳細討論了C++的異常對象按值傳遞和按引用傳遞的兩種方式,本文繼續(xù)討論最后的一種的方式:按指針傳遞。
異常對象在什么時候構造?
1、與按值和按引用傳遞異常的方式相比,在按指針傳遞異常的方式下,異常對象的構造方式有很大的不同。它必須是在堆中動態(tài)構造的異常對象,或者是全局性static的變量。示例程序如下:
void main()
{
try
{
// 動態(tài)在堆中構造的異常對象
throw new MyMemoryException("ex_obj1");
}
catch(MyException* e)
{
cout<GetName()< delete e;
}
}
2、注意,通過指針方式傳遞的異常對象不能是局部變量,否則后果很嚴重,示例如下:
void main()
{
try
{
// 局部變量,異常對象
MyMemoryException ex_obj1("ex_obj1");
// 拋出一個指針類型的異常
// 注意:這樣做很危險,因為ex_obj1這個對象離開了這個作用域即
// 析構銷毀
throw &ex_obj1;
}
catch(MyException* e)
{
// 下面語句雖然不會導致程序崩潰,但是e->GetName()取得的結果
// 也是不對的。
cout<GetName()< // 這條語句會導致程序崩潰
// delete e;
}
}
程序運行的結果是:
構造一個MyException異常對象,名稱為:ex_obj1
構造一個MyMemoryException異常對象,名稱為:ex_obj1
銷毀一個MyMemoryException異常對象,名稱為:ex_obj1
銷毀一個MyException異常對象,名稱為:ex_obj1
捕獲到一個MyException*類型的異常,名稱為:
異常對象按指針方式被傳遞
指針是歷史悠久的一種數(shù)據(jù)類型形式,這可以追溯到C語言和PASCAL語言中。異常對象按指針方式傳遞,當然更是不會發(fā)生對象的拷貝復制過程。所以這種方式傳遞異常對象是效率的,它從拋出異常、捕獲異常再到異常錯誤處理結束過程中,總共只會發(fā)生的一次對象的構造過程,那就是異常對象最初在堆中的動態(tài)創(chuàng)建時的初始化的構造過程。也看看示例程序吧!如下:
void main()
{
try
{
// 動態(tài)在堆中構造的異常對象
throw new MyMemoryException("ex_obj1");
}
// 注意:這里是定義了按指針方式傳遞異常對象
catch(MyException* e)
{
cout<GetName()< delete e;
}
}
程序運行的結果是:
構造一個MyException異常對象,名稱為:ex_obj1
構造一個MyMemoryException異常對象,名稱為:ex_obj1
捕獲到一個MyException*類型的異常,名稱為:ex_obj1
銷毀一個MyMemoryException異常對象,名稱為:ex_obj1
銷毀一個MyException異常對象,名稱為:ex_obj1
呵呵!程序的運行結果是不是顯示出異常對象只有一次的構造過程。挺好挺好!
異常對象什么時候被銷毀
異常對象動態(tài)地在堆上被創(chuàng)建,同時它也要動態(tài)的被銷毀,否則就必然會發(fā)生內存泄漏。那么異常對象應該在什么時候被銷毀比較合適呢?當然應該是在catch block塊中處理完畢后再銷毀它才比較合理。示例如下:
void main()
{
try
{
// 動態(tài)在堆中構造的異常對象
throw new MyMemoryException("ex_obj1");
}
catch(MyException* e)
{
cout<GetName()< // 這里需要顯示的刪除異常對象
delete e;
}
}
指針方式下,異常對象會發(fā)生對象切片嗎?
當然不會,試都不用試,阿愚非常有把握確信這一點。
總結
(1) 被拋出的異常對象不能是局部變量或臨時變量,必須是在堆中動態(tài)構造的異常對象,或者是全局性static的變量;
(2) 異常對象只會被構造一次;
(3) catch 后面帶的異常對象的作用域僅限于catch bock中;
(4) 異常對象動態(tài)地在堆上被創(chuàng)建,同時它也要動態(tài)的被銷毀。
至此為止,C++的異常對象的傳遞的三種方式(指針、傳值和引用)都已經討論過了,主人公阿愚到此算是松了一大口氣,終于把這塊比較難肯一點的骨頭給拿下了(呵呵!^_^)。為了更進一步鞏固這些知識。下一篇文章準備對這三種方式來一個綜合性的大比較!去看看吧!
異常對象在什么時候構造?
1、與按值和按引用傳遞異常的方式相比,在按指針傳遞異常的方式下,異常對象的構造方式有很大的不同。它必須是在堆中動態(tài)構造的異常對象,或者是全局性static的變量。示例程序如下:
void main()
{
try
{
// 動態(tài)在堆中構造的異常對象
throw new MyMemoryException("ex_obj1");
}
catch(MyException* e)
{
cout<
}
}
2、注意,通過指針方式傳遞的異常對象不能是局部變量,否則后果很嚴重,示例如下:
void main()
{
try
{
// 局部變量,異常對象
MyMemoryException ex_obj1("ex_obj1");
// 拋出一個指針類型的異常
// 注意:這樣做很危險,因為ex_obj1這個對象離開了這個作用域即
// 析構銷毀
throw &ex_obj1;
}
catch(MyException* e)
{
// 下面語句雖然不會導致程序崩潰,但是e->GetName()取得的結果
// 也是不對的。
cout<
// delete e;
}
}
程序運行的結果是:
構造一個MyException異常對象,名稱為:ex_obj1
構造一個MyMemoryException異常對象,名稱為:ex_obj1
銷毀一個MyMemoryException異常對象,名稱為:ex_obj1
銷毀一個MyException異常對象,名稱為:ex_obj1
捕獲到一個MyException*類型的異常,名稱為:
異常對象按指針方式被傳遞
指針是歷史悠久的一種數(shù)據(jù)類型形式,這可以追溯到C語言和PASCAL語言中。異常對象按指針方式傳遞,當然更是不會發(fā)生對象的拷貝復制過程。所以這種方式傳遞異常對象是效率的,它從拋出異常、捕獲異常再到異常錯誤處理結束過程中,總共只會發(fā)生的一次對象的構造過程,那就是異常對象最初在堆中的動態(tài)創(chuàng)建時的初始化的構造過程。也看看示例程序吧!如下:
void main()
{
try
{
// 動態(tài)在堆中構造的異常對象
throw new MyMemoryException("ex_obj1");
}
// 注意:這里是定義了按指針方式傳遞異常對象
catch(MyException* e)
{
cout<
}
}
程序運行的結果是:
構造一個MyException異常對象,名稱為:ex_obj1
構造一個MyMemoryException異常對象,名稱為:ex_obj1
捕獲到一個MyException*類型的異常,名稱為:ex_obj1
銷毀一個MyMemoryException異常對象,名稱為:ex_obj1
銷毀一個MyException異常對象,名稱為:ex_obj1
呵呵!程序的運行結果是不是顯示出異常對象只有一次的構造過程。挺好挺好!
異常對象什么時候被銷毀
異常對象動態(tài)地在堆上被創(chuàng)建,同時它也要動態(tài)的被銷毀,否則就必然會發(fā)生內存泄漏。那么異常對象應該在什么時候被銷毀比較合適呢?當然應該是在catch block塊中處理完畢后再銷毀它才比較合理。示例如下:
void main()
{
try
{
// 動態(tài)在堆中構造的異常對象
throw new MyMemoryException("ex_obj1");
}
catch(MyException* e)
{
cout<
delete e;
}
}
指針方式下,異常對象會發(fā)生對象切片嗎?
當然不會,試都不用試,阿愚非常有把握確信這一點。
總結
(1) 被拋出的異常對象不能是局部變量或臨時變量,必須是在堆中動態(tài)構造的異常對象,或者是全局性static的變量;
(2) 異常對象只會被構造一次;
(3) catch 后面帶的異常對象的作用域僅限于catch bock中;
(4) 異常對象動態(tài)地在堆上被創(chuàng)建,同時它也要動態(tài)的被銷毀。
至此為止,C++的異常對象的傳遞的三種方式(指針、傳值和引用)都已經討論過了,主人公阿愚到此算是松了一大口氣,終于把這塊比較難肯一點的骨頭給拿下了(呵呵!^_^)。為了更進一步鞏固這些知識。下一篇文章準備對這三種方式來一個綜合性的大比較!去看看吧!

