SymbianOS異常三步曲之三:兩段構造

爲了在堆上分配一個CExample對象內存空間,調用該類的構造函數,如果構造函數本身就異常退出了,那麼分配給對象的內存和構造函數中已經分配的內存都將泄漏,因此,C++的構造函數絕對不能發生異常。如果,爲了初始化一個對象,必須要編寫發生異常的代碼,例如內存分配或讀取可能丟失的文件,損壞了的配置文件等,這時候,就需要使用兩段構造了。
一、兩段構造的格式:
編寫一個類時,將構造代碼分爲兩部分:
1、  一個基本的不會發生異常退出的構造函數
這個構造函數將被new操作符調用,它隱式的調用基類的構造函數,另外還可以調用那些不會發生異常退出的函數,也可以以默認值或傳入構造函數的參數來初始化成員變量。
 
2、  一個類方法(通常稱爲ConstructL())
只要通過new操作符分配並構造的對象被壓入了清除棧,該方法就可以單獨調用了,它將繼續完成對象的構造過程,這裏面可以安全的執行那些可能發生異常退出的操作。即使發生了異常,由於之前已經將對象指針入棧,清除棧可以調用類的析構函數來釋放所有已經成功分配的資源,並回收分配給對象本身的內存。
實例:
class CExample : public CBase
{
       public:
              static CExample* NewL();//靜態函數
              static CExample* NewLC();//靜態函數
              ~CExample();//析構函數必須public,否則delete不能調用
       private:
              CExample();//絕對不能異常
              ConstructL();//將構造時所有可能異常的代碼放在這裏
}
 
爲了安全和使用上的方便,往往在類的定義裏面添加兩個靜態的函數NewL()NewLC(),作用主要是將兩段構造關聯到一起。
CExample* CExample::NewLC()
{
       CExample* me = new(ELeave) CExample();
       CleanupStack::PushL(me);
       me->ConstrutL();
       return me;
}
CExample* CExample::NewL()
{
       CExample me = CExample::NewLC();
       CleanupStack::Pop(me);
       return me;
}
當然,NewL()NewLC()函數是可以接受參數的,並可以通過參數來初始化對象。這些參數可以傳遞給簡單構造函數,也可以傳遞給ContructL(),或者同時傳遞給兩者。
 
二、使用須知:
如果你的類派生自某基類,而該基類也實現了ConstructL(),那麼就要保證當對象被構造時,如果需要,基類的ConstructL()也會被調用(C++能夠保證基類第一段簡單構造函數會被構造函數自動調用),因此,需要我們自己在ConstructL()中顯式的(通過域操作符)調用所有基類的ConstructL(),這樣才能保證在初始化派生類對象之前,基類子對象都已經被完全構造了。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章