| 導購 | 订阅 | 在线投稿
分享
 
 
 

Delphi和C++的語法區別

來源:互聯網網民  2006-12-05 19:16:37  評論

目錄

Delphi永遠沒辦法在棧上創建一個對象

Delphi的構造函數更象是個類方法(靜態成員函數)

Delphi的析構函數中可以調用純虛方法

Delphi在構造對象時自動將成員變量清零

Delphi構造函數中抛出異常會自動先調用析構函數

Delphi簡化了COM接口的AddRef、Release和QueryInterface

一、Delphi永遠沒辦法在棧上創建一個對象

下面是一段常見的的Delphi代碼,在過程的開頭聲明本過程所需要的全部局部變量:

procedure Foo;

var

obj: TObject; //這句容易被C++程序員誤會。

begin

...

end;

C++程序員會以爲obj這個變量就是TObject對象實例本身,會以爲這一句是在棧上聲明並構造了TObject類的一個對象實例,他們會與下面的C++代碼混淆:

void Foo() { CObject obj; //這一句的確在棧上構造了CObject類的

... //一個對象實例,並且將在離開Foo函數時自動析構它

}

牢記一點,在Delphi裏,永遠不可能在棧上構造一個對象,也永遠不可能對一個對象進行值傳遞,程序員能看到的是“指向對象實例的指針”,簡單地說“一切皆指針”,上例中obj其實就是一個“TObject類型的指針”,當它在棧上被聲明的時候,它的值不可知(與C++一樣),也沒有任何對象被構造出來。上述代碼翻譯成C++,基本上就是:

void Foo() {

CObject * obj; // 聲明一個CObject類型的指針

// 但沒有任何對象被構造或與之關聯

...

}

作爲一個佐證,在Delphi裏,sizeof(TObject), sizeof(Self), sizeof(obj) 結果都是4,即一個32位指針的大小。

二、Delphi的構造函數更象是個類方法(靜態成員函數)

由于Delphi不允許在棧上構造對象,那麽對象實例就只能創建在堆上,Delphi沒有new關鍵字(倒有一個名爲New的procedure),而是用一種有別于C++的語法來(在堆上)構造對象:

procedure Foo;

var

obj: TObject; //obj本質上只是一個TObject類型的指針

begin

obj := TObject.Create; //在堆上構造一個TObject對象實例並將其地址賦值給obj

obj.Free; //令obj指向的對象析構

end;

與C++一樣,在堆上構造的函數不會在離開作用域的時候被自動析構,所以在離開Foo這個過程之些,要調用TObject的Free方法來析構它。Free方法會調用Destroy析構函數,只不過在調用Destroy之前會判斷Self是否爲空,如果爲空就直接返回。Delphi裏的Self,就是C++裏的this。

Delphi是單根繼承,所有類都從TObject派生而來,而所有類的構造函數一定名爲Create,而析構函數一定名爲Destroy,當然,析構函數肯定是虛函數。

從聲明的形式上看,Create方法象是一個成員函數,但從使用上看,它更象一個類方法(C++裏叫靜態成員函數),因爲調用它的時候,限定名不是對象,而是類名(Txxxxx.Create)。

三、Delphi的析構函數中可以調用純虛方法

由于在Delphi的析構函數Destroy裏,可以調用任何純虛函數(在C++裏這一點是不可想象的),所以可以認爲這個時候,虛方法表有一定未被破壞,那麽,如果基類就可以決定析構時一定要調用的函數,哪怕這個函數是個虛函數,甚至純虛函數。

四、Delphi在構造的時候自動將成員變量清零

任何一個Delphi中的類,當它被構造後,它的所有成員變量被清零,布爾型初始爲False,字符串初始爲空,整型和浮點型初始化爲0……而C++沒有這樣的保證

五、Delphi構造函數中抛出異常會自動先調用析構函數

Delphi裏,如果構造函數中抛出了異常,則會自動先執行析構函數,然後再把異常向外抛出;而在C++裏,構造函數中若有異常抛出,則析構函數是不會被調用的。

六、Delphi簡化了COM接口中的AddRef、Release和QueryInterface

C++裏一般用模板對COM接口進行封裝,而在Delphi裏,AddRef、Release以及QueryInterface都被編譯器隱藏掉了,當把一個IUnknown類型的變量(本質上也是一個指針)賦值給另一個變量時,編譯器在背後自動AddRef,當一個IUnknown變量離開作用域的時候(再也沒有人使用它),Release被自動調用,而QueryInterface被抽象爲AS運算符:

procedure Foo(const AParam: IUnknown);

var

bar: IUnknown;

other: IStream;

begin

bar := AParam; //AParam指向的實例由于賦值操作被AddRef一次

other := bar as IStream; //調用了一次QueryInterface,引用計數再次加一

end; //返回時,other和bar都離開作用域,分別被調用Release各一次

C++中用模板(比如_com_ptr)也可以使引用計數自動化,不過QueryInterface就沒那麽方便了。

 
特别声明:以上内容(如有图片或视频亦包括在内)为网络用户发布,本站仅提供信息存储服务。
 
目錄 [url=http://dev.csdn.net/#stack_instance]Delphi永遠沒辦法在棧上創建一個對象[/url] [url=http://dev.csdn.net/#class_method]Delphi的構造函數更象是個類方法(靜態成員函數)[/url] [url=http://dev.csdn.net/#call_pure_virtual]Delphi的析構函數中可以調用純虛方法[/url] [url=http://dev.csdn.net/#auto_clear]Delphi在構造對象時自動將成員變量清零[/url] [url=http://dev.csdn.net/#constructor_exception]Delphi構造函數中抛出異常會自動先調用析構函數[/url] [url=http://dev.csdn.net/#COM]Delphi簡化了COM接口的AddRef、Release和QueryInterface[/url] 一、Delphi永遠沒辦法在棧上創建一個對象 下面是一段常見的的Delphi代碼,在過程的開頭聲明本過程所需要的全部局部變量: procedure Foo; var obj: TObject; //這句容易被C++程序員誤會。 begin ... end; C++程序員會以爲obj這個變量就是TObject對象實例本身,會以爲這一句是在棧上聲明並構造了TObject類的一個對象實例,他們會與下面的C++代碼混淆: void Foo() { CObject obj; //這一句的確在棧上構造了CObject類的 ... //一個對象實例,並且將在離開Foo函數時自動析構它 } 牢記一點,在Delphi裏,永遠不可能在棧上構造一個對象,也永遠不可能對一個對象進行值傳遞,程序員能看到的是“指向對象實例的指針”,簡單地說“一切皆指針”,上例中obj其實就是一個“TObject類型的指針”,當它在棧上被聲明的時候,它的值不可知(與C++一樣),也沒有任何對象被構造出來。上述代碼翻譯成C++,基本上就是: void Foo() { CObject * obj; // 聲明一個CObject類型的指針 // 但沒有任何對象被構造或與之關聯 ... } 作爲一個佐證,在Delphi裏,sizeof(TObject), sizeof(Self), sizeof(obj) 結果都是4,即一個32位指針的大小。 二、Delphi的構造函數更象是個類方法(靜態成員函數) 由于Delphi不允許在棧上構造對象,那麽對象實例就只能創建在堆上,Delphi沒有new關鍵字(倒有一個名爲New的procedure),而是用一種有別于C++的語法來(在堆上)構造對象: procedure Foo; var obj: TObject; //obj本質上只是一個TObject類型的指針 begin obj := TObject.Create; //在堆上構造一個TObject對象實例並將其地址賦值給obj obj.Free; //令obj指向的對象析構 end; 與C++一樣,在堆上構造的函數不會在離開作用域的時候被自動析構,所以在離開Foo這個過程之些,要調用TObject的Free方法來析構它。Free方法會調用Destroy析構函數,只不過在調用Destroy之前會判斷Self是否爲空,如果爲空就直接返回。Delphi裏的Self,就是C++裏的this。 Delphi是單根繼承,所有類都從TObject派生而來,而所有類的構造函數一定名爲Create,而析構函數一定名爲Destroy,當然,析構函數肯定是虛函數。 從聲明的形式上看,Create方法象是一個成員函數,但從使用上看,它更象一個類方法(C++裏叫靜態成員函數),因爲調用它的時候,限定名不是對象,而是類名(Txxxxx.Create)。 三、Delphi的析構函數中可以調用純虛方法 由于在Delphi的析構函數Destroy裏,可以調用任何純虛函數(在C++裏這一點是不可想象的),所以可以認爲這個時候,虛方法表有一定未被破壞,那麽,如果基類就可以決定析構時一定要調用的函數,哪怕這個函數是個虛函數,甚至純虛函數。 四、Delphi在構造的時候自動將成員變量清零 任何一個Delphi中的類,當它被構造後,它的所有成員變量被清零,布爾型初始爲False,字符串初始爲空,整型和浮點型初始化爲0……而C++沒有這樣的保證 五、Delphi構造函數中抛出異常會自動先調用析構函數 Delphi裏,如果構造函數中抛出了異常,則會自動先執行析構函數,然後再把異常向外抛出;而在C++裏,構造函數中若有異常抛出,則析構函數是不會被調用的。 六、Delphi簡化了COM接口中的AddRef、Release和QueryInterface C++裏一般用模板對COM接口進行封裝,而在Delphi裏,AddRef、Release以及QueryInterface都被編譯器隱藏掉了,當把一個IUnknown類型的變量(本質上也是一個指針)賦值給另一個變量時,編譯器在背後自動AddRef,當一個IUnknown變量離開作用域的時候(再也沒有人使用它),Release被自動調用,而QueryInterface被抽象爲AS運算符: procedure Foo(const AParam: IUnknown); var bar: IUnknown; other: IStream; begin bar := AParam; //AParam指向的實例由于賦值操作被AddRef一次 other := bar as IStream; //調用了一次QueryInterface,引用計數再次加一 end; //返回時,other和bar都離開作用域,分別被調用Release各一次 C++中用模板(比如_com_ptr)也可以使引用計數自動化,不過QueryInterface就沒那麽方便了。
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有