说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Delphi 4增訂的Object Pascal

HTML文档下载 WORD文档下载 PDF文档下载
Delphi 4增訂的Object Pascal

總結來說,Delphi 4的Object Pascal增訂了以下幾大部分:

新增加數種內定資料型態。

Dynamic Arrays

Method and Routine Overloading

Default Parameters.

Implementating interfaces by delegation,可用以下的寫法:

property MyInterface: IMyInterface read FMyInterface

implements IMyInterface;

新增的內定資料型態

整數方面:

新增加Int64這種長度六十四位元,範圍從-2^63 to 2^63 - 1。

32-bit unsigned integer新增加Longword型態,範圍從0..4294967295。

Cardinal的範圍調整成與上述Longword型態相同。

浮點數方面:

Real型態基於效率考量,由過去佔用48-bit調整成64-bits,

新增加Real48型態,精確度與過去的Real相同,仍是48-bit。

Dynamic Array

Delphi 4問世之前,Delphi程式設計師若需要動態長度的陣列,在不得已的情況下,往往採用以下這種「表面上陣列的語法,但實際自己配置管理記憶體」的方式來處理動態陣列:

#0001 procedure TForm1.Button1Click(Sender: TObject);

#0002 type

#0003 TIntegerArray = array[0..0] of integer;

#0004 PIntegerArray = ^TIntegerArray;

#0005 var

#0006 pArrayOfInteger: PIntegerArray;

#0007 j: integer;

#0008 begin

#0009 GetMem(pArrayOfInteger

10 * SizeOf(Integer));

#0010 for j := 0 to 9 do

#0011 pArrayOfInteger^[j] := j;

#0012 FreeMem(pArrayOfInteger

10 * SizeOf(Integer));

#0013 end;

如果應用Delphi 4新增加的Dynamic Array,則可改用以下的方式:

var MyFlexibleArray: array of Real;

定義之後,以 SetLength 函數改變陣列實際配置的記憶體大小,例如:

SetLength(MyFlexibleArray

20); // 0..19

方便很多,是嗎?若想知道Dynamic Array實際長度,請分別以High與Low函數判斷,傳回「-1」時,表示是一個該陣列的長度為零,例如:

#0001 procedure TForm1.Button2Click(Sender: TObject);

#0002 var

#0003 A: array of Integer;

#0004 begin

#0005 ShowMessage(IntToStr(High(A))); // -1

#0006 SetLength(A

3);

#0007 ShowMessage(IntToStr(High(A))); // 3

#0008 A := nil;

#0009 ShowMessage(IntToStr(High(A))); // -1

#0010 end;

上述的0008這列,指定nil值將會釋放陣列所配置到的記憶體。

值得注意的是,Compiler對於Dynamic Array並不會自動進行所謂的「Copy-on-Write」。請看以下的程式例:

#0001 procedure TForm1.Button1Click(Sender: TObject);

#0002 var

#0003 A

B: array of Integer;

#0004 begin

#0005 SetLength(A

1);

#0006 A[0] := 1;

#0007 B := A;

#0008 B[0] := 2;

#0009 ShowMessage(IntToStr(A[0])); // ==> 2

#0010 end;

0008這列改的雖是B[0],但Compiler顯然還沒有聰明到在可能修改陣列內容時,將陣列內容複製一份出來(Copy on (possible) Write),於是,0009這列程式顯示的結果仍是2。

於是,若要進行兩陣列各索引項目一對一的內容複製,只好自行寫迴圈一一複製,或者,採用較為簡便的寫法 ── 呼叫Copy函數:

#0001 procedure TForm1.Button4Click(Sender: TObject);

#0002 var

#0003 A

B: array of Integer;

#0004 begin

#0005 SetLength(A

1);

#0006 A[0] := 1;

#0007 B := Copy(A

0

1);

#0008 B[0] := 2;

#0009 ShowMessage(IntToStr(A[0])); // ==> 1

#0010 ShowMessage(IntToStr(B[0])); // ==> 2

#0011 end;

最後,請不要將Dynamic Array與第二章提到的Open Array(開放陣列)搞混了。函式參數的開放陣列,語法雖與Dynamic Array差不多,但開放陣列指的是:不限定傳入函式的陣列長度,Dynamic Array則是指:可變長度的陣列,兩者畢竟有所不同。以下是一則我準備的程式範例,不難看出兩者之間的差異:

#0001 type

#0002 TDynamicInteger = array of integer;

#0003

#0004 procedure Clear_OpenArray(var A: array of Integer);

#0005 var

#0006 I: Integer;

#0007 begin

#0008 for I := 0 to High(A) do A[I] := 0;

#0009 // SetLength(A

20); // 不可以這麼寫

#0010 end;

#0011

#0012 // 注意

以下兩種寫法又有不同喔

#0013 // I: procedure Clear_DynamicArray(A: TDynamicInteger);

#0014 // II: procedure Clear_DynamicArray(var A: TDynamicInteger);

#0015 procedure Clear_DynamicArray(var A: TDynamicInteger);

#0016 var

#0017 I: Integer;

#0018 begin

#0019 for I := 0 to High(A) do A[I] := 0;

#0020 SetLength(A

20); // 如果是Dynamic Array

可以這麼寫

#0021 end;

#0022

#0023 procedure TForm1.Button3Click(Sender: TObject);

#0024 var

#0025 A: TDynamicInteger;

#0026 begin

#0027 SetLength(A

3);

#0028 Clear_OpenArray(A);

#0029 ShowMessage(IntToStr(High(A))); // -1

#0030 Clear_DynamicArray(A);

#0031 // 以下這列的結果

要看 Cleary_DynamicArray 的

#0032 // 參數有沒有寫 var

#0033 ShowMessage(IntToStr(High(A)));

#0034 end;

請幫我注意0004的Clear_OpenArray,傳入的是「由整數構成的陣列,不限定陣列的長度」,0015的Clear_DynamicArray的寫法則是「接受一個可變動陣列長度的動態陣列」,若不這樣寫,當場就變成了開放陣列了。

Method and Routine Overloading

所謂的Method Overloading,簡單地說:一個以上的函式使用相同的函式名稱。這項特性是Object Pascal長久以來一直有人想要卻一直沒有支援的期盼,終於,Delphi 4多了一個保留字:overload ── 相同名稱的兩個函式,只要在宣告時額外加上overload,即使函式的參數型態不同,Delphi也會視呼叫當時傳入的參數資料型態,決定該呼叫哪一個函式。例如以下這則例子:

#0001 // 兩個 Divide 都必須寫overload保留字

#0002 function Divide(X

Y: Double): Double; overload;

#0003 begin

#0004 Result := X / Y;

#0005 end;

#0006

#0007 function Divide(X

Y: Integer): Integer; overload;

#0008 begin

#0009 Result := X div Y;

#0010 end;

#0011

#0012 procedure TForm1.Button1Click(Sender: TObject);

#0013 var

#0014 a

b

c: integer;

#0015 i

j

k: Double;

#0016 begin

#0017 a := 10;

#0018 b := 3;

#0019 i := 10;

#0020 j := 3;

#0021 c := Divide(a

b);

#0022 k := Divide(i

j);

#0023 ShowMessage(IntToStr(c)); // 3

#0024 ShowMessage(FloatToStr(k)); // 3.333333...

#0025 end;

請幫我注意到0002與0007這兩列的Divide函數,函數名稱相同,但傳入的參數型態與函數的傳回值並不相同,即使如此,0023與0024呼叫到Divide時,還是會視當時參數的型態型態,決定該呼叫哪一個Divide。

很方便,是嗎?有了這項特性,我們就可以寫出應用範圍更廣彈性更大的函數──卻不必為每一種情況各自取一個函數名稱,同時,這項特性也使得函數呼叫的方式更為一致,真是一項早該支援的特性。除了一般的程序與函數,物件的方法也可以採用overload寫法,對於「物件.方法」的撰寫與呼叫,肯定更能提供簡便與彈性。

overload可不可以應用在不同的兩個單元呢?答案是可以的,但是完全相同的函式宣告不能再寫一次。例如上述程式的0007-0010,可以移到其他單元,原來的單元只要uses這個新的單元,函數呼叫時仍然有Overloading的效果。可是,如果將0007-0010的程式碼移到其他單元卻忘了刪除原來位置的程式,換句話說,兩個單元各有一個完全長得一樣的函式,編譯時Delphi就搞不清楚了,結果自然是無法編譯。當然啦!同一個單元同一個範圍發生這樣事也是不許的,各Overloading的函式,在函式宣告上多少總有些不同。

Default Parameters

過去,函式如果定義了六個參數,那麼,寫作函式呼叫的原始碼時,就一定得乖乖地傳入六個參數,不許多也不許少。若是應用「Default Parameters」,可以只傳入五個(或者更少)。那...,那其他沒給的參數怎麼辦?沒關係,函式內部的程式將自動以預設值代入,稍後我會說明其寫法。

舉例來說,Windows API中有一個蠻好用的函數叫MessageBox,呼叫此函數將出現一通用對話盒,不管是顯示訊息或者徵詢使用者意見,都十分好用。像是以下這道敘述將產生如次頁的對話盒,提醒使用者定期備份資料:

Application.MessageBox('程式要結束了喔! 請記得定期備份資料'

'訊息'

MB_OK + MB_ICONINFORMATION);

除了顯示資料,經由最後一個參數,彈性地搭配各位元旗標,就可以製作出不同按鈕的對話盒,詢問使用者「是」、「否」、「取消」等簡單的問題。

應用Default Parameters的寫法,我們可以寫一個類似以下的函數:

#0001 function MyMessageBox(Prompt: string;

#0002 Caption: string = '訊息';

#0003 Flag: LongInt = MB_OK + MB_ICONINFORMATION): integer;

#0004 begin

#0005 Result := Application.MessageBox(

#0006 PChar(Prompt)

PChar(Caption)

Flag);

#0007 end;

#0008

#0009 procedure TForm1.Button1Click(Sender: TObject);

#0010 begin

#0011 MyMessageBox('程式要結束了喔! 請記得定期備份資料');

#0012 end;

如此一來,我們既能有一個完整支援MessageBox的函數,只想顯示文字時,也能有一個精簡型式的函數可用。大家應該明顯看得出來:不必寫成兩個函數。

觀察上述程式的寫法,其實也蠻容易的,只不過是在定義函數參數時,一併給定初值。

不過,實際動手去寫時,還是會發現一些限制。繼續這個例子來說,參數的預設值一定得是常數,另外,如果某一個參數開始給預設值,接在後頭的參數也必須用Default Parameters的寫法。為什麼得有這項限制?以上例來說,如果0001-0003我改成:

#0001 function MyMessageBox(Prompt: string;

#0002 Caption: string = '訊息';

#0003 Flag: LongInt): integer;

那麼,只傳入兩個參數進去時,Delphi怎麼知道第二個參數該是Captioin或者是「Caption按預設值,第二個參數代入Flag」。Visual Basic對此的解法是在呼叫函數時,一併寫明各參數名稱與值的對應,由於這個緣故,Visual Basic甚至允許參數的次序不同也沒關係,因為,各參數與其值的對應關係在呼叫函式時已一併註明清楚。很可惜的,Delphi 4雖有Default Parametets,但還不支援以下的函數呼叫方式:

MyMessageBox('程式要結束了喔! 請記得定期備份資料'

Flag = ...);

雖然如此,上述「如果某一個參數開始給預設值,接在後頭的參數也必須用Default Parameters的寫法」這項限制,多少還是可以搭配前一節的Overloading加以彌補:

#0001 function MyMessageBox(Prompt: string;

#0002 Caption: string = '訊息';

#0003 Flag: LongInt = MB_OK + MB_ICONINFORMATION): integer; overload;

#0004 begin

#0005 Result := Application.MessageBox(

#0006 PChar(Prompt)

PChar(Caption)

Flag);

#0007 end;

#0008

#0009 function MyMessageBox(Prompt: string;

#0010 Flag: LongInt;

#0011 Caption: string = '訊息'

#0012 ): integer; overload;

#0013 begin

#0014 Result := Application.MessageBox(

#0015 PChar(Prompt)

PChar(Caption)

Flag);

#0016 end;

#0017

#0018 procedure TForm1.Button1Click(Sender: TObject);

#0019 begin

#0020 MyMessageBox('程式要結束了喔! 請記得定期備份資料');

#0021 MyMessageBox('別說我沒告訴你喔!'

MB_OK);

#0022 end;

(好煩的程式,一再提醒要記得備份。:p)

請幫我注意這次改寫過的程式0009-0012,我重新調整了各參數的次序,並且分別在兩同名函數都加上了overload保留字,這樣,Delphi就知道該呼叫的是哪一個了。

谷歌锁死SDK,能阻止Android碎片化吗? KitCam团队专访:为应用做加法也能雄踞榜首 谷歌哭了:Replicant 4.0 SDK发布搅乱大局 忍者神龟与禅宗启示:如何突破移动广告困境 Linux会是更好的游戏平台?暴雪是这么认为的! 新型恶意软件瞄准Java服务器 AWS被纳为“战略物资”市值或可达到300亿美元? 十张图带你入门Map/Reduce 低端Android野心,Intel发布Atom Z2420处理器 淘宝网的技术发展史(一)——个人网站时代 看Pinterest如何通过架构变化将EC2成本降低了62% 内容vs渠道:法国电信商Free叫板Google 让网站成为应用:Firefox OS掀起革命风潮 屌丝伞兵的逆袭:4人+盛大+远程+最佳手游 新年头彩:Chartboost喜获1900万美元融资 高富帅跻身移动领域 福特开放车载声控API 传低端iPhone最低只要99美元 你怎么看? 辉煌不再 Encanto超级计算机可能被拆分“出售” 知己知彼 企业应用移足云端必须清楚的10大方面 NVIDIA推Android掌机:七年孕育可否成就野心? 人民日报:2013关于新媒体的8个猜想 互联网大时代成就创新小企业 移动互联网创新论坛报道 Mobile Detect:判断移动设备类型的开源PHP类 我是如何Hack Facebook Employees Secure Files Transfer服务的 投资可再生能源:Google 2亿美元投资风力农场 构筑商业生态系统 阿里巴巴集团全面变革组织架构和管理体系 美国众多银行网站遭DDoS攻击 疑似伊朗所为 构建高可扩Web架构和分布式系统实战 CES2013 AMD发布移动处理器路线图和环绕计算概念 对话Linus Torvalds:大多黑客甚至连指针都未理解 PaaS玩家们,怎么演好自己的角色? NetGuardian??哪为兄弟有啊,给我一份copy~~~~~~~~~~~~ 关于自增长字段使用的问题,高手请进 这一贴,分就少点了,就这么多啦 有人能告诉我广东省C程序员与JAVA程序员的薪水比较吗?为什么会有这种差距呢 请问用javaApplet如何控制IE界面? 点对点的讨论 水平考试与资格考试及格分别是多少分? 如何再网页中实现打印功能,份也打印。 我发现了一个网站的BUG,我该怎样进去? 到处都是泡泡,俺看的想吐,晚上再来算了。 怪事, 屏幕变黑白 我的问题_6 MYSQL中like的问题 请教打印预览问题 请问,如果我想把,file edit tools window这个主菜单栏动态去掉,怎么做? 如何用程序代码实现在Memo文本编辑框中被选中的文字加下划线。 怎样分析tcp报文(我很急呀) *.idl文件如何使用? 各位大侠,怎么写一个php在线打分的程序阿? 我测试一下 感兴趣的去试试! IE外壳扩展的程序 Delphi 6.0的一个Bug??? 我怎么把字符串放进缓冲里?急急急!!! 恭喜 zhipop 喜得漂亮的可爱的千金 几个小问题想请教大家 如何将浏览器的地址栏里的IE图标换成自己的图标? r俺明天想去给我的宝马生生级,不算显示器,3000元左右,请各位大侠们赐教该什么配置 2000下写的程序,NT 4.0workstation上为什么不能跑? 启用新主页下载数据窗口编辑器 请教Qbasic中的几个问题..... 用BCB如何向Oracle8.0.5中更新BLOB 用ODBC编程时发现错误:nvarchar 类型无数据类型同其绑定,用CString 出错!如何解决? 救命,救命!!!!!!!!!!!! 【 这两天好像来了很多新人嘛!来报个到吧! 】 请教:如将一个 FormView 的 ScrollBar 去掉 在asp中怎么定义可变长的数组? 关于文本框的问题(你能回答吗?) X档案第三季有一集叫《网络情人》,讲的什么内容? 如何登陆interbase de local server? 确定星座是按农历,还是公历????? 请问哪里能买到苹果7300主板,大概多少钱? vc高手快来帮我 我可以通过style定义普通字体的大小,却不能定义表格中字体的大小 BDE + SQL AnyWhere6.0问题!求救!SOS! 最新消息:泡泡是个PLMM 如何实现关机前所有文挡的自动保存 兄弟要进行一项庞大的工程 . 输全国县以上地区的编码. 我用powerbulider设计了一个报表,如何能在vc程序中使用这个报表 如何用回车键代替tab键在sle之间移动焦点 讨论:关于翻译英文文章的版权问题????????? 家庭电路中,电压一定220V,电炉子的电阻很大,根据P=U方/R,功率应该很小,但为什么电炉子的功率却很大?而且其他用电器的电阻越大,功率还越大? 请问:一千瓦等于多少马力 500克等于多少个100毫克 24v的交流电热圈功率是1000瓦,那么电流是多少?能电倒人吗? 空调多少匹是怎么换算出来的,空调匹数跟瓦数怎么换算,1千瓦等于多少马力? 2000毫升水有多少千克此问题对我很严重.还请各位尽量回答我. 一个电炉子功率2000瓦每天用5小时一个月按30天计算电费是多少 一马力等于多少瓦? 50毫升B摩尔每升的ALCL3溶液加入50毫升A摩尔每升氢氧化钠溶液当A小于等于3b时生成氢氧化铝的沉淀物质的量 电炉子工作时,是将电能转化成热能,电炉子工作时,是将电能转化成热能;电炉子工作时,是将电能转化成热;电炉子工作时,是将电能转化成内能!哪种说法正确!三者有什么不同? 功率和马力是怎么换算? 向20毫升氯化铝溶液中滴入2摩尔每升氢氧化钠溶液时,沉淀质量与所滴加氢氧化钠溶液体积(ml)铝离子完全沉淀时沉淀质量为0.78g,假设溶液中有氢氧化铝0.39克,则此时用去氢氧化钠溶液的体积 一种炉子,电能的!既可以做电煮锅,又可以取暖!不是普通的光波炉之类的,有一定的高度,面积差不多80*80cm 还可以用作打麻将时取暖!知道的朋友介绍一下!最好给个链接!了解功能 价钱...不是电 功率和马力怎么换算现在汽车说的是功率,和原来的马力怎么换算? 向20毫升氯化铝溶液中滴入2摩尔每升的氢氧化钠溶液时,得到氢氧化铝沉淀的质量与所滴加氢氧化钠溶液体积关系如图所示.(1)图中A点表示的意义是____________.B点表示的意义是____________.(2)上 600瓦电烤火炉每小时用几度电? 1千瓦等于多少马力 如何配置0.5摩尔每升的无水碳酸钠溶液500毫升 我用最大功率1000瓦的电插座,插上一个做饭的电炉,是耗电1000瓦的.用多久拔掉安全点? 136匹马力等于多少千瓦也就是新B200的功率,随便说一下,这车真的买来值吗?是不是比以前的奔驰要缩水一些? 实验室用NaCO3·10H2O 晶体配制500毫升0.1摩尔每毫升的碳酸钠溶液 应称取NaCO3·10H2O 多少克 减震弹簧是一圈一圈紧挨着,还是一圈一圈有空隙 汽油机1千瓦等于多少马力汽油机和柴油机一样吗 取500毫升碳酸钠溶液与300毫升浓度为一摩尔每升的盐酸反应,在不断搅拌下将碳酸钠溶液逐滴滴入盐酸中与将盐酸滴入碳酸钠溶液中,所产生气体的物质的量之比为3:2.则碳酸钠的浓度是多少? 一度电是不是就等于一千瓦 那 1匹马力等于多少千瓦 配制500毫升2摩尔每升的硫酸溶液需浓度为百分之九十八,其密度为1.84克每立方米的浓硫酸呵水各多少 一千瓦是不是等于一度电?总搞不清,说清原因 1马力等于多少千瓦 如何配制溶液500毫升的碳酸钠溶液 一千瓦一小时几度电 请问1千瓦等于多少马力 用98%浓硫酸配制500毫升1.0摩尔每升的硫酸溶液? 800瓦的电器一小时会耗多少度电? 多少伏等于一千瓦?一千瓦等于多少电流?同上 1马力等于多少千瓦时 1500瓦的电器一小时能用几度电 一度电是一千瓦时还是3.6*1000000瓦时 1马力等于多少功率 1000瓦等于多少安 一千瓦一个小时一度电如何计算出来的介绍一下这一块儿的..我不是很懂... 一升等于多少公斤谢谢了,大神帮忙啊 电冰箱的额定功率是70瓦,耗电量是0.5kw.h/24h,问每小时用电量多少,每天用电多少W? 114磅是多少公斤?磅和公斤的换算公式是怎样的呀? 舍得酒广告的含义 功率1000瓦的电器一个小时耗电量是多少 血的单位CC跟毫升跟克是怎么换算的 舍得酒经典台词 请问功率1000瓦的电器,它的电流是多少? 体积CC和毫升怎么换算? 舍得的含义?如何舍得,如何取舍 1安培等于多少瓦? cc和毫升怎么换算啊?cc和毫升有什么关系?它们之间应该怎么换算?2000cc等于多少毫升?急用!谢谢了!~ 怎样辨别舍得酒的真假想买一瓶给老爸,还怕买到假酒,请懂行的朋友帮帮忙!积分不多, 请问35瓦等于多少安培?1:35瓦等于多少安培?2:蓄电池上标有12v/7ah 请问后面的7ah是什么意思? CC与毫升是怎么换算的? 250毫升等于多少毫克 一安培等于多少瓦 毫升怎样换算成斤,公式是怎样的.我说的是酒 请问250毫克等于250毫升吗?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn