上一篇文章簡(jiǎn)單討論了一下對(duì)象的成員函數(shù)拋出異常時(shí)的處理情況。本文中將繼續(xù)討論當(dāng)在構(gòu)造函數(shù)中拋出異常時(shí),程序的執(zhí)行情況又如何?這有點(diǎn)復(fù)雜呀!而且主人公阿愚還覺(jué)得這蠻有點(diǎn)意思!
構(gòu)造函數(shù)中拋出的異常
1、標(biāo)準(zhǔn)C++中定義構(gòu)造函數(shù)是一個(gè)對(duì)象構(gòu)建自己,分配所需資源的地方,一旦構(gòu)造函數(shù)執(zhí)行完畢,則表明這個(gè)對(duì)象已經(jīng)誕生了,有自己的行為和內(nèi)部的運(yùn)行狀態(tài),之后還有對(duì)象的消亡過(guò)程(析構(gòu)函數(shù)的執(zhí)行)。可誰(shuí)能保證對(duì)象的構(gòu)造過(guò)程一定能成功呢?說(shuō)不定系統(tǒng)當(dāng)前的某個(gè)資源不夠,導(dǎo)致對(duì)象不能完全構(gòu)建好自己(人都有畸形兒,更何況別的呢?朋友們!是吧!),因此通過(guò)什么方法來(lái)表明對(duì)象的構(gòu)造失敗了呢?C++程序員朋友們知道,C++中的構(gòu)造函數(shù)是沒(méi)有返回值的,所以不少關(guān)于C++編程方面的書(shū)上得出結(jié)論:“因?yàn)闃?gòu)造函數(shù)沒(méi)有返回值,所以通知對(duì)象的構(gòu)造失敗的方法那就是在構(gòu)造函數(shù)中拋出異?!薄V魅斯⒂薹浅2煌膺@種說(shuō)法,誰(shuí)說(shuō)的,便不信邪!雖然C++標(biāo)準(zhǔn)規(guī)定構(gòu)造函數(shù)是沒(méi)有返回值,可我們知道每個(gè)函數(shù)實(shí)際上都會(huì)有一個(gè)返回值的,這個(gè)值被保存在eax寄存器中,因此實(shí)際上是有辦法通過(guò)編程來(lái)實(shí)現(xiàn)構(gòu)造函數(shù)返回一個(gè)值給上層的對(duì)象創(chuàng)建者。當(dāng)然即便是構(gòu)造函數(shù)真的不能有返回值,我們也可以通過(guò)一個(gè)指針類型或引用類型的出參來(lái)獲知對(duì)象的構(gòu)造過(guò)程的狀態(tài)。示例如下:
class MyTest_Base
{
public:
MyTest_Base (int& status)
{
//do other job
// 由于資源不夠,對(duì)象構(gòu)建失敗
// 把status置0,通知對(duì)象的構(gòu)建者
status = 0;
}
protected:
};
void main()
{
int status;
MyTest_Base obj1(status);
// 檢查對(duì)象的構(gòu)建是否成功
if(status ==0) cout << “對(duì)象構(gòu)建失敗” << endl;
}
程序運(yùn)行的結(jié)果是:
對(duì)象構(gòu)建失敗
是啊!上面我們不也得到了對(duì)象構(gòu)造的成功與否的信息了嗎?可大家有沒(méi)有覺(jué)得這當(dāng)中有點(diǎn)問(wèn)題?主人公阿愚建議大家在此停留片刻,仔細(xì)想想它會(huì)有什么問(wèn)題?OK!也許大家都知道了問(wèn)題的所在,來(lái)驗(yàn)證一下吧!
class MyTest_Base
{
public:
MyTest_Base (int& status)
{
//do other job
// 由于資源不夠,對(duì)象構(gòu)建失敗
// 把status置0,通知對(duì)象的構(gòu)建者
status = 0;
}
virtual ~ MyTest_Base ()
{
cout << “銷毀一個(gè)MyTest_Base類型的對(duì)象” << endl;
}
protected:
};
void main()
{
int status;
MyTest_Base obj1(status);
// 檢查對(duì)象的構(gòu)建是否成功
if(status ==0) cout << “對(duì)象構(gòu)建失敗” << endl;
}
程序運(yùn)行的結(jié)果是:
對(duì)象構(gòu)建失敗
銷毀一個(gè)MyTest_Base類型的對(duì)象
沒(méi)錯(cuò),對(duì)象的析構(gòu)函數(shù)被運(yùn)行了,這與C++標(biāo)準(zhǔn)中所規(guī)定的面向?qū)ο蟮囊恍┨匦允怯袥_突的。一個(gè)對(duì)象都沒(méi)有完成自己的構(gòu)造,又何來(lái)析構(gòu)!好比一個(gè)夭折的畸形兒還沒(méi)有出生,又何來(lái)死之言。因此這種方法是行不通的。那怎么辦?那就是上面那個(gè)結(jié)論中的后一句話是對(duì)的,通知對(duì)象的構(gòu)造失敗的方法那就是在構(gòu)造函數(shù)中拋出異常,但原因卻不是由于構(gòu)造函數(shù)沒(méi)有返回值而造成的。恰恰相反,C++標(biāo)準(zhǔn)中規(guī)定構(gòu)造函數(shù)沒(méi)有返回值正是由于擔(dān)心很容易與面向?qū)ο蟮囊恍┨匦韵鄾_突,因此干脆來(lái)個(gè)規(guī)定,構(gòu)造函數(shù)不能有返回值(主人公阿愚的個(gè)人理解,有不同意見(jiàn)的朋友歡迎討論)。
2、構(gòu)造函數(shù)中拋出異常將導(dǎo)致對(duì)象的析構(gòu)函數(shù)不被執(zhí)行。哈哈^-^,阿愚很開(kāi)心,瞧瞧!如果沒(méi)有C++的異常處理機(jī)制鼎立支持,C++中的面向?qū)ο筇匦远紵o(wú)法真正實(shí)現(xiàn)起來(lái),C++標(biāo)準(zhǔn)總不能規(guī)定所有的對(duì)象都必須成功構(gòu)造吧!這也太理想化了,也許只有等到共產(chǎn)主義社會(huì)實(shí)現(xiàn)的那一天(CPU可以隨便拿,內(nèi)存可以隨便拿,所有的資源都是你的?。┎耪f(shuō)不定有可能·····,所以說(shuō)C++的異常處理和面向?qū)ο蟠_實(shí)是誰(shuí)也離不開(kāi)誰(shuí)。當(dāng)然示例還是要看一下,如下:
class MyTest_Base
{
public:
MyTest_Base (string name = “”) : m_name(name)
{
throw std::exception(“在構(gòu)造函數(shù)中拋出一個(gè)異常,測(cè)試!”);
cout << “構(gòu)造一個(gè)MyTest_Base類型的對(duì)象,對(duì)象名為:”< }
virtual ~ MyTest_Base ()
{
cout << “銷毀一個(gè)MyTest_Base類型的對(duì)象,對(duì)象名為:”< }
void Func() throw()
{
throw std::exception(“故意拋出一個(gè)異常,測(cè)試!”);
}
void Other() {}
protected:
string m_name;
};
void main()
{
try
{
// 對(duì)象構(gòu)造時(shí)將會(huì)拋出異常
MyTest_Base obj1(“obj1”);
obj1.Func();
obj1.Other();
}
catch(std::exception e)
{
cout << e.what() << endl;
}
catch(...)
{
cout << “unknow exception”<< endl;
}
}
程序的運(yùn)行結(jié)果將會(huì)驗(yàn)證:“構(gòu)造函數(shù)中拋出異常將導(dǎo)致對(duì)象的析構(gòu)函數(shù)不被執(zhí)行”
構(gòu)造函數(shù)中拋出的異常
1、標(biāo)準(zhǔn)C++中定義構(gòu)造函數(shù)是一個(gè)對(duì)象構(gòu)建自己,分配所需資源的地方,一旦構(gòu)造函數(shù)執(zhí)行完畢,則表明這個(gè)對(duì)象已經(jīng)誕生了,有自己的行為和內(nèi)部的運(yùn)行狀態(tài),之后還有對(duì)象的消亡過(guò)程(析構(gòu)函數(shù)的執(zhí)行)。可誰(shuí)能保證對(duì)象的構(gòu)造過(guò)程一定能成功呢?說(shuō)不定系統(tǒng)當(dāng)前的某個(gè)資源不夠,導(dǎo)致對(duì)象不能完全構(gòu)建好自己(人都有畸形兒,更何況別的呢?朋友們!是吧!),因此通過(guò)什么方法來(lái)表明對(duì)象的構(gòu)造失敗了呢?C++程序員朋友們知道,C++中的構(gòu)造函數(shù)是沒(méi)有返回值的,所以不少關(guān)于C++編程方面的書(shū)上得出結(jié)論:“因?yàn)闃?gòu)造函數(shù)沒(méi)有返回值,所以通知對(duì)象的構(gòu)造失敗的方法那就是在構(gòu)造函數(shù)中拋出異?!薄V魅斯⒂薹浅2煌膺@種說(shuō)法,誰(shuí)說(shuō)的,便不信邪!雖然C++標(biāo)準(zhǔn)規(guī)定構(gòu)造函數(shù)是沒(méi)有返回值,可我們知道每個(gè)函數(shù)實(shí)際上都會(huì)有一個(gè)返回值的,這個(gè)值被保存在eax寄存器中,因此實(shí)際上是有辦法通過(guò)編程來(lái)實(shí)現(xiàn)構(gòu)造函數(shù)返回一個(gè)值給上層的對(duì)象創(chuàng)建者。當(dāng)然即便是構(gòu)造函數(shù)真的不能有返回值,我們也可以通過(guò)一個(gè)指針類型或引用類型的出參來(lái)獲知對(duì)象的構(gòu)造過(guò)程的狀態(tài)。示例如下:
class MyTest_Base
{
public:
MyTest_Base (int& status)
{
//do other job
// 由于資源不夠,對(duì)象構(gòu)建失敗
// 把status置0,通知對(duì)象的構(gòu)建者
status = 0;
}
protected:
};
void main()
{
int status;
MyTest_Base obj1(status);
// 檢查對(duì)象的構(gòu)建是否成功
if(status ==0) cout << “對(duì)象構(gòu)建失敗” << endl;
}
程序運(yùn)行的結(jié)果是:
對(duì)象構(gòu)建失敗
是啊!上面我們不也得到了對(duì)象構(gòu)造的成功與否的信息了嗎?可大家有沒(méi)有覺(jué)得這當(dāng)中有點(diǎn)問(wèn)題?主人公阿愚建議大家在此停留片刻,仔細(xì)想想它會(huì)有什么問(wèn)題?OK!也許大家都知道了問(wèn)題的所在,來(lái)驗(yàn)證一下吧!
class MyTest_Base
{
public:
MyTest_Base (int& status)
{
//do other job
// 由于資源不夠,對(duì)象構(gòu)建失敗
// 把status置0,通知對(duì)象的構(gòu)建者
status = 0;
}
virtual ~ MyTest_Base ()
{
cout << “銷毀一個(gè)MyTest_Base類型的對(duì)象” << endl;
}
protected:
};
void main()
{
int status;
MyTest_Base obj1(status);
// 檢查對(duì)象的構(gòu)建是否成功
if(status ==0) cout << “對(duì)象構(gòu)建失敗” << endl;
}
程序運(yùn)行的結(jié)果是:
對(duì)象構(gòu)建失敗
銷毀一個(gè)MyTest_Base類型的對(duì)象
沒(méi)錯(cuò),對(duì)象的析構(gòu)函數(shù)被運(yùn)行了,這與C++標(biāo)準(zhǔn)中所規(guī)定的面向?qū)ο蟮囊恍┨匦允怯袥_突的。一個(gè)對(duì)象都沒(méi)有完成自己的構(gòu)造,又何來(lái)析構(gòu)!好比一個(gè)夭折的畸形兒還沒(méi)有出生,又何來(lái)死之言。因此這種方法是行不通的。那怎么辦?那就是上面那個(gè)結(jié)論中的后一句話是對(duì)的,通知對(duì)象的構(gòu)造失敗的方法那就是在構(gòu)造函數(shù)中拋出異常,但原因卻不是由于構(gòu)造函數(shù)沒(méi)有返回值而造成的。恰恰相反,C++標(biāo)準(zhǔn)中規(guī)定構(gòu)造函數(shù)沒(méi)有返回值正是由于擔(dān)心很容易與面向?qū)ο蟮囊恍┨匦韵鄾_突,因此干脆來(lái)個(gè)規(guī)定,構(gòu)造函數(shù)不能有返回值(主人公阿愚的個(gè)人理解,有不同意見(jiàn)的朋友歡迎討論)。
2、構(gòu)造函數(shù)中拋出異常將導(dǎo)致對(duì)象的析構(gòu)函數(shù)不被執(zhí)行。哈哈^-^,阿愚很開(kāi)心,瞧瞧!如果沒(méi)有C++的異常處理機(jī)制鼎立支持,C++中的面向?qū)ο筇匦远紵o(wú)法真正實(shí)現(xiàn)起來(lái),C++標(biāo)準(zhǔn)總不能規(guī)定所有的對(duì)象都必須成功構(gòu)造吧!這也太理想化了,也許只有等到共產(chǎn)主義社會(huì)實(shí)現(xiàn)的那一天(CPU可以隨便拿,內(nèi)存可以隨便拿,所有的資源都是你的?。┎耪f(shuō)不定有可能·····,所以說(shuō)C++的異常處理和面向?qū)ο蟠_實(shí)是誰(shuí)也離不開(kāi)誰(shuí)。當(dāng)然示例還是要看一下,如下:
class MyTest_Base
{
public:
MyTest_Base (string name = “”) : m_name(name)
{
throw std::exception(“在構(gòu)造函數(shù)中拋出一個(gè)異常,測(cè)試!”);
cout << “構(gòu)造一個(gè)MyTest_Base類型的對(duì)象,對(duì)象名為:”<
virtual ~ MyTest_Base ()
{
cout << “銷毀一個(gè)MyTest_Base類型的對(duì)象,對(duì)象名為:”<
void Func() throw()
{
throw std::exception(“故意拋出一個(gè)異常,測(cè)試!”);
}
void Other() {}
protected:
string m_name;
};
void main()
{
try
{
// 對(duì)象構(gòu)造時(shí)將會(huì)拋出異常
MyTest_Base obj1(“obj1”);
obj1.Func();
obj1.Other();
}
catch(std::exception e)
{
cout << e.what() << endl;
}
catch(...)
{
cout << “unknow exception”<< endl;
}
}
程序的運(yùn)行結(jié)果將會(huì)驗(yàn)證:“構(gòu)造函數(shù)中拋出異常將導(dǎo)致對(duì)象的析構(gòu)函數(shù)不被執(zhí)行”

