先看一個(gè)例子。首先,我要寫一個(gè)vector;其次,為了使用方便,我需要提供一個(gè)帶 size 參數(shù)的構(gòu)造函數(shù)。要求就這兩點(diǎn)。
那么,勢(shì)必要:
class vector
{
public:
vector(size_t size)
{
// ...
m_pData = new int[size]; // 假設(shè)就是 int 這樣的基本類型好了,以避免下面可能出現(xiàn)的離題
// ...
}
};
問(wèn)題來(lái)了。new 不是有可能失敗嗎?失敗了在老編譯器里會(huì)返回 NULL(這個(gè)情形也先無(wú)視),在新編譯器里會(huì)拋異常。那么,在這里要不要進(jìn)行檢查呢?如果檢查:
try
{
m_pData = new int[size];
}
catch (...)
{
}
catch到了。那么在這里可以干啥呢?似乎。。。啥也干不了!作為構(gòu)造函數(shù),沒(méi)法使用返回值,自然只能使用異常來(lái)提示外界;既然本來(lái)就是異常,我又何必在這里 try 一次呢?(假設(shè)這里沒(méi)有其他錯(cuò)誤要處理,也假設(shè)這里的類型是int之類的基本類型,不會(huì)出現(xiàn)執(zhí)行元素的構(gòu)造函數(shù)失敗的情形)
既然這里的 try 讓我們?nèi)绱藷o(wú)奈,那么就不必 try 了。這個(gè)時(shí)候,我需要給 vector(size_t size) 標(biāo)記上 throw 嗎?如果不標(biāo)記,使用者怎么知道這里可能會(huì)有異常?如果標(biāo)記了,或者沒(méi)標(biāo)記但使用者意識(shí)到了,那么他會(huì)這樣用:
try
{
vector v(10);
// Task with v
// ...
// ...
// ...
}
catch (...)
{
// Error handler
}
因?yàn)?v 的作用域被限制在了 try 內(nèi),所以所有的與 v 相關(guān)的邏輯代碼全部要放在 try 內(nèi)部了。這種樣子似乎與 C# 很像!在 C# 里,try...catch... 是標(biāo)準(zhǔn)的做法;但是在 C++ 里,似乎不會(huì)如此經(jīng)常地用 try catch,要不然,為什么我見(jiàn)過(guò)的 C++ 代碼都不是這樣子的呢??jī)赡昵霸诮鹕綄?shí)習(xí)的時(shí)候,有一次我把 try...catch 當(dāng)做通用的錯(cuò)誤處理來(lái)做,所有的錯(cuò)誤都搞成一種異常,返回值僅返回正常值。結(jié)果董波叔叔說(shuō),這樣子是不對(duì)滴,但是沒(méi)給出讓我信服理由,可能就是,C++ 的 try...catch 的性能很不好之類的。(C# 以及 Java 的 try...catch 的性能好嗎?)
好,既然大家都不這么辦,是不是這里也不用 try 了?于是,內(nèi)存分配錯(cuò)誤就讓它自生自滅了……記得以前某本書上看到,說(shuō)這種情形下的處理,僅僅是一個(gè)道德問(wèn)題而已。真的無(wú)解嗎?
如果放寬要求,不要求在構(gòu)造函數(shù)提供內(nèi)存分配,那倒是有一種解法——分兩階段構(gòu)造:
class vector
{
public:
vector()
{
// ...
}
bool allocate(size_t size)
{
try
{
m_pData = new int[size];
}
catch (...)
{
return false;
}
if (m_pData == NULL)
{
return false;
}
// Other code ...
return true;
}
};
但是使用起來(lái)就不“方便”了。現(xiàn)實(shí)中,這種情形倒是存在,如 CWindow 的 Create,還有啥啥啥的 Init 等等。
真的沒(méi)有辦法兼顧方便與安全嗎?
posted on 2010-03-30 22:31
溪流 閱讀(2384)
評(píng)論(15) 編輯 收藏 引用 所屬分類:
C++