《delphi高手突破》節選二 (轉)

worldblog發表於2007-12-12
《delphi高手突破》節選二 (轉)[@more@]

完成了第三章 異常及錯誤處理,節選一節

構造與異常

這個話題在C++社群中經常會被提起,而在社群中似乎從來沒有人注意過。也許由於語言的特性,使得Delphi員不必關心這個問題。但我想Delphi程式設計師也應該對該問題有所瞭解,知道語言為我們提供了什麼而使得我們如此輕鬆,不必理會它。正所謂“身在福中須知福”。

我們知道,類的建構函式是沒有返回值的,如果建構函式構造失敗,不可能依靠返回錯誤程式碼。那麼,在程式中如何標識建構函式的失敗呢?最“標準”的方法就是:丟擲一個異常。

建構函式失敗,意味著物件的構造失敗,那麼丟擲異常之後,這個“半死不活”的物件會被如何處理呢?

在此,我想讀著有必要先對C++對這種情況的處理方式先有個瞭解。

在C++中,建構函式丟擲異常後,解構函式不會被。這種做法是合理的,因為此時物件並沒有被完整構造。

如果建構函式已經做了一些諸如分配、開啟等操作的話,那麼C++類需要有自己的成員來記住做過哪些動作。當然,這樣做對於類的實現者來說非常麻煩,因此一般C++類的實現者都避免在建構函式中丟擲異常(可以提供一個諸如Init和UnInit的成員函式,由建構函式或類的客戶去呼叫它們,以處理初始化失敗的情況)。而每一本C++的經典著作所提供的方案是使用智慧指標(STL的標準類auto_ptr)。

在 Pascal中,這個問題變得非常的簡單,程式設計師不必為此大費周折。如果Object Pascal的類在建構函式中丟擲異常,會自動呼叫類的解構函式(由於解構函式不允許被過載,可以保證只有唯一一個解構函式,因此編譯器不會迷惑於多個解構函式之中)。解構函式中一般會析構成員物件,而Free()方法保證了不會對nil物件(即尚未被建立的成員物件)呼叫解構函式,因此在使得程式碼簡潔優美的前提下,又保證了。

type MyClass = class

private

FStr : PChar; // 字串指標

public

constructor Create();

destructor Destroy(); overr;

end;

 :namespace prefix = o ns = "urn:schemas--com::office" />

constructor MyClass.Create();

begin

FStr := StrAlloc(10); // 建構函式中為字串指標分配記憶體

StrCopy(FStr, 'ABCDEFGHI');

raise Exception.Create('error'); // 丟擲異常,沒有理由,呵呵

end;

 

destructor A.Destroy();

begin

StrDispose(FStr); // 解構函式中釋放記憶體

WriteLn('Free Re');

end;

 

var

Obj : TMyClass;

i : integer;

begin

try

Obj := TMyClass.Create();

Obj.Free();

WriteLn('Succeeded');

except

Obj := nil;

WriteLn('Failed');

end;

 

Read(i); // 暫停螢幕,以便觀察執行結果

end.

 

在這段程式碼中,建構函式丟擲異常,的結果是:

Free Resource

Failed

此時的“Free Resource”輸出是由編譯器自動呼叫解構函式所產生的。

因此,如果類的說明文件或類的作者告知你,類的建構函式可能會丟擲異常,那就要記得用try…except包住它!

C++與Object Pascal對於建構函式丟擲異常後的不同處理方式,其實正是兩種語言的設計思想的體現。C++秉承C的風格,注重,一切交給程式設計師來掌握,編譯器不作多餘動作。Object Pascal繼承Pascal的風格,注重程式的美學意義,編譯器幫助程式設計師完成複雜的工作。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991902/,如需轉載,請註明出處,否則將追究法律責任。

相關文章