|
 |
栏目导栏 |
|
| |
|
|
|
|
 |
资料搜索 |
|
| |
|
|
|
|
 |
热门文章 |
|
| |
|
|
|
|
 |
最新文章 |
|
| |
|
|
|
| |
| |
|
|
|
|
常量变量 1gjyLinux联盟 gjyLinux联盟 Q:如何初始化全局变量? 1gjyLinux联盟 gjyLinux联盟 Q:怎样定于字符串常量? 2gjyLinux联盟 gjyLinux联盟 数据类型 2gjyLinux联盟 gjyLinux联盟 Q:为什么首选用 Integer 或Cardinal? 2gjyLinux联盟 gjyLinux联盟 Q: ByteBool/ WordBool/ LongBool 和Boolean的区别? 3gjyLinux联盟 gjyLinux联盟 Q: ANISIChar和WideChar的区别? 3gjyLinux联盟 gjyLinux联盟 Q:各种字符表示方法? 3gjyLinux联盟 gjyLinux联盟 Q:怎样选择实数类型 ? 3gjyLinux联盟 gjyLinux联盟 Q:日期和时间的区别 ? 3gjyLinux联盟 gjyLinux联盟 Q:数据类型映射及类型转换的区别 ? 4gjyLinux联盟 gjyLinux联盟 Delphi 字符串与 Windows PChar字符串的相互转换 6gjyLinux联盟 gjyLinux联盟 基本语句 8gjyLinux联盟 gjyLinux联盟 If语句 8gjyLinux联盟 gjyLinux联盟 Case语句 8gjyLinux联盟 gjyLinux联盟 过程和函数 9gjyLinux联盟 gjyLinux联盟 Q:引用参数如何传递 9gjyLinux联盟 gjyLinux联盟 Q:Delphi 方法调用有哪些协定? 9gjyLinux联盟 gjyLinux联盟 Q:什么是Forward 声明? 9gjyLinux联盟 gjyLinux联盟 Q:什么是函数重载? 10gjyLinux联盟 gjyLinux联盟 Q:如何使用确省参数? 10gjyLinux联盟 gjyLinux联盟 Q:什么是开放数组参数 ? 11gjyLinux联盟 gjyLinux联盟 单元的工作空间 11gjyLinux联盟 gjyLinux联盟 应用程序内存区 13gjyLinux联盟 gjyLinux联盟 Q:全局内存区,堆,栈之间的区别? 13gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 常量变量gjyLinux联盟 gjyLinux联盟 Q:如何初始化全局变量?gjyLinux联盟 gjyLinux联盟 在Delphi 中,当你声明全程变量时,你可以赋给它一个初值。例如,你可以这样写:gjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 Value: Integer = 10;gjyLinux联盟 gjyLinux联盟 Correct: Boolean = True;gjyLinux联盟 gjyLinux联盟 这种初始化方法只能用于全程变量,不能用于过程或方法的变量。gjyLinux联盟 gjyLinux联盟 Q:怎样定于字符串常量? gjyLinux联盟 gjyLinux联盟 当定义字符串常量时,你可这样写:gjyLinux联盟 gjyLinux联盟 constgjyLinux联盟 gjyLinux联盟 IniName = \'edi.ini\';gjyLinux联盟 gjyLinux联盟 也可以用另一种方式写:gjyLinux联盟 gjyLinux联盟 resourcestringgjyLinux联盟 gjyLinux联盟 IniName = \'edi.ini\';gjyLinux联盟 gjyLinux联盟 上面两个语句都定义了一个常量,也就是定义了一个在程序运行期间保持不变的值,但两者的实现过程却不同,用resourcestring 指令定义的字符串变量将被保存到程序资源的字符串表中。gjyLinux联盟 gjyLinux联盟 数据类型gjyLinux联盟 gjyLinux联盟 variant是一种无需类型检测的数据类型gjyLinux联盟 gjyLinux联盟 整数类型、布尔类型和字符类型(Integer,Boolean,Char)gjyLinux联盟 gjyLinux联盟 表 1: 表示数字的有序数据类型 gjyLinux联盟 gjyLinux联盟 大小 有符号值域 无符号值域gjyLinux联盟 gjyLinux联盟 8 bits ShortInt-128 to 127 Byte0 to 255gjyLinux联盟 gjyLinux联盟 16 bits SmallInt-32768 to 32767 Word0 to 65,535gjyLinux联盟 gjyLinux联盟 32 bits LongInt-2,147,483,648 to 2,147,483,647 LongWord (从 Delphi 4)0 to 4,294,967,295gjyLinux联盟 gjyLinux联盟 64 bits Int64 gjyLinux联盟 gjyLinux联盟 16/32 bits Integer CardinalgjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 Q:为什么首选用 Integer 或Cardinal?gjyLinux联盟 gjyLinux联盟 Integer及Cardinal 类型比较常用,因为它们与CPU内部的数字表示法相对应。gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 Q: ByteBool/ WordBool/ LongBool 和Boolean的区别?gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 在Delphi 3 中,为了与Visual Basic 和 OLE Automation兼容,修改了ByteBool、 WordBool 和LongBool的布尔值,将TRUE值设置为1,FALSE值仍为0;gjyLinux联盟 gjyLinux联盟 Boolean类型布尔值保持不变(TRUE为1,FALSE为0)。gjyLinux联盟 gjyLinux联盟 Q: ANISIChar和WideChar的区别?gjyLinux联盟 gjyLinux联盟 字符有两种不同的表示法:: ANSIChar 和 WideChar。第一种类型代表 8 位的字符,与Windows一直沿用的ANSI(美国国家标准协会)字符集相应;第二种类型代表 16 位的字符,与Windows NT、Windows 95 和 98支持的双字节字符(Unicode)相应。在Delphi 3 中,Char 类型字符与ANSIChar一致。切记,不管在什么环境,前 256 个Unicode 字符与ANSI 字符是完全一致的。gjyLinux联盟 gjyLinux联盟 Q:各种字符表示方法?gjyLinux联盟 gjyLinux联盟 常量字符可用代表它们的符号表示,如‘k’,也可用数字符号表示,如 #78。gjyLinux联盟 gjyLinux联盟 后者还可用Chr函数表示为 Chr(78),用Ord函数可作相反的转换Ord(k)。gjyLinux联盟 gjyLinux联盟 一般来说,对字母、数字或符号,用代表它们的符号来表示较好;而涉及到特殊字符时用数字符号较好。下面列出了常用的特殊字符:gjyLinux联盟 gjyLinux联盟 · #9 跳格 (Tab 键) gjyLinux联盟 gjyLinux联盟 · #10 换行 gjyLinux联盟 gjyLinux联盟 · #13 回车 (Enter 键) gjyLinux联盟 gjyLinux联盟 Q:怎样选择实数类型 ?gjyLinux联盟 gjyLinux联盟 实数类型代表不同格式的浮点数。Single类型占的字节数最小,为4个字节;其次是Double 浮点类型,占8个字节;Extended 浮点类型,占10个字节。这些不同精度的浮点数据类型都与IEEE( 电气和电子工程师协会)标准的浮点数表示法一致,并且 CPU数字协处理器直接支持这些类型,处理速度也最快。gjyLinux联盟 gjyLinux联盟 Q:日期和时间的区别 ?gjyLinux联盟 gjyLinux联盟 Delphi 也用实型数表示日期和时间数据。但为了更准确起见,Delphi 特别定义了TDateTime 数据类型,这是一个浮点类型,因为这个类型必须足够宽,使变量能容纳年、月、日、时、分和秒、甚至毫秒。日期值按天计数,从1899-12-30开始,放在TDateTime 类型的整数部分;时间值则位于十进制数的小数部分。gjyLinux联盟 gjyLinux联盟 TDateTime 不是编译器可直接识别的预定义类型,它在System单元定义:gjyLinux联盟 gjyLinux联盟 typegjyLinux联盟 gjyLinux联盟 TDateTime = type Double;gjyLinux联盟 gjyLinux联盟 使用TDateTime 类型很简单,因为Delphi 为该类型定义了一系列操作函数,表2列出了这些函数。gjyLinux联盟 gjyLinux联盟 表2: TDateTime类型系统例程 gjyLinux联盟 gjyLinux联盟 例程 作用 gjyLinux联盟 gjyLinux联盟 Now 返回当前日期及时间 gjyLinux联盟 gjyLinux联盟 Date 返回当前日期 gjyLinux联盟 gjyLinux联盟 Time 返回当前时间 gjyLinux联盟 gjyLinux联盟 DateTimeToStr 按缺省格式将日期和时间值转换为字符串;特定格式转换可用 FormatDateTime函数 gjyLinux联盟 gjyLinux联盟 DateTimeToString 按缺省格式将日期和时间值拷贝到字符串缓冲区 gjyLinux联盟 gjyLinux联盟 DateToStr 将TDateTime值的日期部分转为字符串 gjyLinux联盟 gjyLinux联盟 TimeToStr 将TDateTime值的时间部分转为字符串 gjyLinux联盟 gjyLinux联盟 FormatDateTime 按特定格式将日期和时间值转换为字符串 gjyLinux联盟 gjyLinux联盟 StrToDateTime 将带有日期和时间信息的字符串转换为TdateTime类型值,如串有误将引发一个异常 gjyLinux联盟 gjyLinux联盟 StrToDate 将带有日期信息的字符串转换为TDateTime类型格式 gjyLinux联盟 gjyLinux联盟 StrToTime 将带有时间信息的字符串转换为TDateTime类型格式 gjyLinux联盟 gjyLinux联盟 DayOfWeek 根据传递的日期参数计算该日期是一星期中的第几天 gjyLinux联盟 gjyLinux联盟 DecodeDate 根据日期值返回年、月、日值 gjyLinux联盟 gjyLinux联盟 DecodeTime 根据时间值返回时、分、秒、毫秒值 gjyLinux联盟 gjyLinux联盟 EncodeDate 组合年、月、日值为TDateTime类型值 gjyLinux联盟 gjyLinux联盟 EncodeTime 组合时、分、秒、毫秒值为TDateTime类型值 gjyLinux联盟 gjyLinux联盟 为了显示怎样使用日期时间类型及其相关例程,我建了一个简单的例子TimeNow。该例子在主窗体中设置了一个按钮和一个列表框(ListBox)。开始执行时,程序自动计算并显示当前的时间及日期,以后每次单击按钮 ,显示从程序开始至当前的时间。gjyLinux联盟 gjyLinux联盟 Q:数据类型映射及类型转换的区别 ?gjyLinux联盟 gjyLinux联盟 类型映射(Typecasting),它使用一个带有目标数据类型名的函数符号:gjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 N: Integer;gjyLinux联盟 gjyLinux联盟 C: Char;gjyLinux联盟 gjyLinux联盟 B: Boolean;gjyLinux联盟 gjyLinux联盟 begingjyLinux联盟 gjyLinux联盟 N := Integer (\'X\');gjyLinux联盟 gjyLinux联盟 C := Char (N);gjyLinux联盟 gjyLinux联盟 B := Boolean (0);gjyLinux联盟 gjyLinux联盟 你可以在字节长度相同的数据类型之间进行类型映射。在有序类型之间或实型数据之间进行类型映射通常是安全的,指针类型及对象之间也可以进行类型映射 ,只要你明白自己在做什么。gjyLinux联盟 gjyLinux联盟 然而,一般来说类型映射是一种较危险的编程技术,因为它允许你访问一个似是而非的值,该值好象是其它值的替身。由于数据类型的内部表示法之间通常互相不匹配,所以当遇到错误时会难以追踪,为此你应尽量避免使用类型映射。gjyLinux联盟 gjyLinux联盟 类型转换例程。表3中总结了各种类型转换例程。其中有些例程所涉及的数据类型将在下一节中讨论。 注意表中没有包括特殊类型(如TDateTime 和variant)的转换例程,也没包括用于格式化处理的特殊例程,如Format 和FormatFloat 例程。gjyLinux联盟 gjyLinux联盟 表3:类型转换系统例程gjyLinux联盟 gjyLinux联盟 例程 作用 gjyLinux联盟 gjyLinux联盟 Chr 将一个有序数据转换为一个ANSI字符 gjyLinux联盟 gjyLinux联盟 Ord 将一个有序类型值转换为它的序号 gjyLinux联盟 gjyLinux联盟 Round 转换一个实型值为四舍五入后的整型值 gjyLinux联盟 gjyLinux联盟 Trunc 转换一个实型值为小数截断后的整型值 gjyLinux联盟 gjyLinux联盟 Int 返回浮点数的整数部分 gjyLinux联盟 gjyLinux联盟 IntToStr 将数值转换为字符串 gjyLinux联盟 gjyLinux联盟 IntToHex 将数值转换为十六进制数字符串 gjyLinux联盟 gjyLinux联盟 StrToInt 将字符串转换为一个整型数,如字符串不是一个合法的整型将引发异常 gjyLinux联盟 gjyLinux联盟 StrToIntDef 将字符串转换为一个整数,如字符串不合法返回一个缺省值 gjyLinux联盟 gjyLinux联盟 Val 将字符串转换为一个数字(传统Turbo Pascal例程用于向后兼容) gjyLinux联盟 gjyLinux联盟 Str 将数字转换为格式化字符串(传统Turbo Pascal例程用于向后兼容) gjyLinux联盟 gjyLinux联盟 StrPas 将零终止字符串转换为Pascal类型字符串,在32位Delphi中这种类型转换是自动进行的 gjyLinux联盟 gjyLinux联盟 StrPCopy 拷贝一个Pascal类型字符串到一个零终止字符串, 在32位Delphi中这种类型转换是自动进行的 gjyLinux联盟 gjyLinux联盟 StrPLCopy 拷贝Pascal类型字符串的一部分到一个零终止字符串 gjyLinux联盟 gjyLinux联盟 FloatToDecimal 将一个浮点数转换为包含指数、数字及符号的十进制浮点记录类型 gjyLinux联盟 gjyLinux联盟 FloatToStr 将浮点值转换为缺省格式的字符串 gjyLinux联盟 gjyLinux联盟 FloatToStrF 将浮点值转换为特定格式的字符串 gjyLinux联盟 gjyLinux联盟 FloatToText 使用特定格式,将一个浮点值拷贝到一个字符串缓冲区 gjyLinux联盟 gjyLinux联盟 FloatToTextFmt 同上面例程,使用特定格式,将一个浮点值拷贝到一个字符串缓冲区 gjyLinux联盟 gjyLinux联盟 StrToFloat 将一个Pascal字符串转换为浮点数 gjyLinux联盟 gjyLinux联盟 TextToFloat 将一个零终止字符串转换为浮点数 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 Delphi 还定义了一个Pointer 数据类型,它表示无类型的指针(就象C语言中的void* )。如果你使用无类型指针,你应该用GetMem 例程,而不是New例程,因为GetMem 例程能用于内存分配大小不确定的情况。gjyLinux联盟 gjyLinux联盟 虽然在Delphi中不常使用指针,但是你经常会用一个极为相似的结构--引用(references)。每个对象实例实际上是一个隐含的指针,或说是对其实际数据的引用,利用引用,你能象用其他数据类型一样使用对象变量。gjyLinux联盟 gjyLinux联盟 Delphi 字符串与 Windows PChar字符串的相互转换 gjyLinux联盟 gjyLinux联盟 长字符串为零终止串,这意味着长字符串完全与Windows使用的C语言零终止串兼容,这给长字符串使用带来了便利。一个零终止串是一个字符序列,该序列以一个零字节(或null)结尾。零终止串在Delphi中可用下标从零开始的字符数组表示,C语言就是用这种数组类型定义字符串,因此零终止字符数组在Windows API 函数(基于C语言)中很常见。由于Pascal长字符串与C语言的零终止字符串完全兼容,因此当需要把字符串传递给Windows API 函数时,你可以直接把长字符串映射为PChar 类型。gjyLinux联盟 gjyLinux联盟 下例把一个窗体的标题拷贝给PChar 字符串(用API 函数GetWindowText),然后再把它拷贝给按钮的Caption 属性,代码如下:gjyLinux联盟 gjyLinux联盟 procedure TForm1.Button1Click (Sender: TObject);gjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 S1: String;gjyLinux联盟 gjyLinux联盟 begingjyLinux联盟 gjyLinux联盟 SetLength (S1, 100);gjyLinux联盟 gjyLinux联盟 GetWindowText (Handle, PChar (S1), Length (S1));gjyLinux联盟 gjyLinux联盟 Button1.Caption := S1;gjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 注意:代码中用SetLength函数为字符串分配内存,假如内存分配失败,那么程序就会崩溃;如果你直接用PChar 类型传递值(而不是象以以上代码那样接受一个值),那么代码会很简单,因为不需要定义临时字符串,也不需要初始化串。下面代码把一个Label(标签)控件的Caption 属性作为参数传递给了API函数,只需要简单地把属性值映射为PChar类型:gjyLinux联盟 gjyLinux联盟 SetWindowText (Handle, PChar (Label1.Caption));gjyLinux联盟 gjyLinux联盟 当需要把WideString 映射为Windows兼容类型时,你必须用PWideChar 代替PChar进行转换,WideString常用于OLE和 COM 程序。gjyLinux联盟 gjyLinux联盟 刚才展现了长字符串的优点,现在谈谈它的弊端。当你把长字符串转换为PChar 类型时可能会引发一些问题,问题根本在于:转换以后字符串及其内容将由你来负责,Delphi 不再管了。现在把上面Button1Click代码稍作修改:gjyLinux联盟 gjyLinux联盟 procedure TForm1.Button2Click(Sender: TObject);gjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 S1: String;gjyLinux联盟 gjyLinux联盟 begingjyLinux联盟 gjyLinux联盟 SetLength (S1, 100);gjyLinux联盟 gjyLinux联盟 GetWindowText (Handle, PChar (S1), Length (S1));gjyLinux联盟 gjyLinux联盟 S1 := S1 + \' is the title\'; // this won\'t workgjyLinux联盟 gjyLinux联盟 Button1.Caption := S1;gjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 程序编译通过,但执行结果会令你惊讶,因为按钮的标题并没变,所加的常量字符串没有添加到按钮标题中。问题原因是Windows写字符串时(在GetWindowText API调用中),Windows 没有正确设置Pascal 长字符串的长度。Delphi 仍可以输出该字符串,并能通过零终止符判断字符串何时结束,但是如果你在零终止符后添加更多的字符,那么这些字符将被忽略。gjyLinux联盟 gjyLinux联盟 怎么解决这个问题呢?解决方法是告诉系统把GetWindowText API函数返回的字符串再转换成Pascal字符串。然而,如果你用以下代码:gjyLinux联盟 gjyLinux联盟 S1 := String (S1);gjyLinux联盟 gjyLinux联盟 Delphi 系统将不予理睬,因为把一种类型转换为它自己的类型是无用的操作。为获得正确的Pascal 长字符串,需要你把字符串重新映射为一个PChar 字符串,然后让Delphi 再把它转回到字符串:gjyLinux联盟 gjyLinux联盟 S1 := String (PChar (S1));gjyLinux联盟 gjyLinux联盟 实际上,你可以跳过字符串转换(S1 := PChar (S1));, 因为在Delphi中Pchar转换到string是自动执行的,最终代码如下:gjyLinux联盟 gjyLinux联盟 procedure TForm1.Button3Click(Sender: TObject);gjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 S1: String;gjyLinux联盟 gjyLinux联盟 begingjyLinux联盟 gjyLinux联盟 SetLength (S1, 100);gjyLinux联盟 gjyLinux联盟 GetWindowText (Handle, PChar (S1), Length (S1));gjyLinux联盟 gjyLinux联盟 S1 := String (PChar (S1));gjyLinux联盟 gjyLinux联盟 S1 := S1 + \' is the title\';gjyLinux联盟 gjyLinux联盟 Button3.Caption := S1;gjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 另一个办法是用PChar 字符串的长度重新设定Delphi 字符串长度,可以这样写:gjyLinux联盟 gjyLinux联盟 SetLength (S1, StrLen (PChar (S1)));gjyLinux联盟 gjyLinux联盟 当调用Windows API 函数时会遇到这种实际问题,那时你就不得不考虑这一复杂情况了。gjyLinux联盟 gjyLinux联盟 基本语句gjyLinux联盟 gjyLinux联盟 If语句gjyLinux联盟 gjyLinux联盟 if CheckBox2.Checked thengjyLinux联盟 gjyLinux联盟 ShowMessage (\'CheckBox2 is checked\')gjyLinux联盟 gjyLinux联盟 elsegjyLinux联盟 gjyLinux联盟 ShowMessage (\'CheckBox2 is NOT checked\');gjyLinux联盟 gjyLinux联盟 要注意的是,不能在第一句之后、else 关键词之前加分号,否则编译器将告知语法错误。实际上,if-then-else 语句是单纯的一条语句,因此不能在语句中间加分号。gjyLinux联盟 gjyLinux联盟 Case语句 gjyLinux联盟 gjyLinux联盟 如果你的if语句变得非常复杂,有时可以用case语句代替它。case语句包括用来选值的表达式、可能值序列或一个取值范围。这些值应该是常量,并且它们必须唯一,而且应属于有序类型。Case语句最后可以带一个else 语句,当没有一个标签与选择器的值一致时,执行else语句。下面是两个简单的例子:gjyLinux联盟 gjyLinux联盟 case Number ofgjyLinux联盟 gjyLinux联盟 1: Text := \'One\';gjyLinux联盟 gjyLinux联盟 2: Text := \'Two\';gjyLinux联盟 gjyLinux联盟 3: Text := \'Three\';gjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 case MyChar ofgjyLinux联盟 gjyLinux联盟 \'+\' : Text := \'Plus sign\';gjyLinux联盟 gjyLinux联盟 \'-\' : Text := \'Minus sign\';gjyLinux联盟 gjyLinux联盟 \'*\', \'/\': Text := \'Multiplication or division\';gjyLinux联盟 gjyLinux联盟 \'0\'..\'9\': Text := \'Number\';gjyLinux联盟 gjyLinux联盟 \'a\'..\'z\': Text := \'Lowercase character\';gjyLinux联盟 gjyLinux联盟 \'A\'..\'Z\': Text := \'Uppercase character\';gjyLinux联盟 gjyLinux联盟 elsegjyLinux联盟 gjyLinux联盟 Text := \'Unknown character\';gjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 过程和函数gjyLinux联盟 gjyLinux联盟 Q:引用参数如何传递 gjyLinux联盟 gjyLinux联盟 Pascal 例程的传递参数可以是值参也可以是引用参数。值参传递是缺省的参数传递方式:即将值参的拷贝压入栈中,例程使用、操纵的是栈中的拷贝值,不是原始值。gjyLinux联盟 gjyLinux联盟 当通过引用传递参数时,没有按正常方式把参数值的拷贝压栈(避免拷贝值压栈一般能加快程序执行速度),而是直接引用参数原始值,例程中的代码也同样访问原始值,这样就能在过程或函数中改变参数的值。引用参数用关键字var 标示。gjyLinux联盟 gjyLinux联盟 参数引用技术在大多数编程语言中都有,C语言中虽没有,但C++中引入了该技术。在C++中,用符号 &表示引用;在VB中,没有ByVal 标示的参数都为引用。gjyLinux联盟 gjyLinux联盟 Q:Delphi 方法调用有哪些协定?gjyLinux联盟 gjyLinux联盟 32位的Delphi 中增加了新的参数传递方法,称为fastcall:只要有可能,传递到CPU寄存器的参数能多达三个,使函数调用操作更快。这种快速调用协定(Delphi 3确省方式)可用register 关键字标示。gjyLinux联盟 gjyLinux联盟 问题是这种快速调用协定与Windows不兼容,Win32 API 函数必须声明使用stdcall 调用协定。这种协定是Win16 API使用的原始Pascal 调用协定和C语言使用的cdecl 调用协定的混合体。gjyLinux联盟 gjyLinux联盟 除非你要调用外部Windows函数或定义Windows 回调函数,否则你没有理由不用新增的快速调用协定。Delphi帮助文件的Calling conventions 主题下,你能找到有关Delphi调用协定的总结内容。gjyLinux联盟 gjyLinux联盟 Q:什么是Forward 声明?gjyLinux联盟 gjyLinux联盟 当使用一个标识符(任何类型)时,编译器必须已经知道该标识符指的是什么。为此,你通常需要在例程使用之前提供一个完整的声明。然而在某些情况下可能做不到这一点,例如过程A调用过程B,而过程B又调用过程A,那么你写过程代码时,不得不调用编译器尚未看到其声明的例程。gjyLinux联盟 gjyLinux联盟 欲声明一个过程或函数,而且只给出它的名字和参数,不列出其实现代码,需要在句尾加forward 关键字:gjyLinux联盟 gjyLinux联盟 procedure Hello; forward;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 当你在一个单元(关于单元的更多内容见下一章)的interface 部分声明一个过程或一个函数时,它被认为是一个forward声明,即使没有forward关键字也一样。gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 Q:什么是函数重载? gjyLinux联盟 gjyLinux联盟 重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同。实际上,编译器是通过检测参数来确定需要调用的例程。gjyLinux联盟 gjyLinux联盟 下面是从VCL的数学单元(Math Unit)中摘录的一系列函数:gjyLinux联盟 gjyLinux联盟 function Min (A,B: Integer): Integer; overload;gjyLinux联盟 gjyLinux联盟 function Min (A,B: Int64): Int64; overload;gjyLinux联盟 gjyLinux联盟 function Min (A,B: Single): Single; overload;gjyLinux联盟 gjyLinux联盟 function Min (A,B: Double): Double; overload;gjyLinux联盟 gjyLinux联盟 function Min (A,B: Extended): Extended; overload;gjyLinux联盟 gjyLinux联盟 当调用方式为Min (10, 20)时,编译器很容易就能判定你调用的是上列第一个函数,因此返回值也是个整数。gjyLinux联盟 gjyLinux联盟 声明重载函数有两条原则:gjyLinux联盟 gjyLinux联盟 · 每个例程声明后面必须添加overload 关键字。 gjyLinux联盟 gjyLinux联盟 · 例程间的参数个数或(和)参数类型必须不同,返回值不能用于区分各例程。 gjyLinux联盟 gjyLinux联盟 Q:如何使用确省参数? gjyLinux联盟 gjyLinux联盟 Delphi 4 中添加了一个新功能,即允许你给函数的参数设定确省值,这样调用函数时该参数可以加上,也可以省略。下例把应用程序全程对象的MessageBox 方法重新包装了一下,用PChar 替代字符串,并设定两个确省值:gjyLinux联盟 gjyLinux联盟 procedure MessBox (Msg: string;gjyLinux联盟 gjyLinux联盟 Caption: string = \'Warning\';gjyLinux联盟 gjyLinux联盟 Flags: LongInt = mb_OK or mb_IconHand);gjyLinux联盟 gjyLinux联盟 begingjyLinux联盟 gjyLinux联盟 Application.MessageBox (PChar (Msg),gjyLinux联盟 gjyLinux联盟 PChar (Caption), Flags);gjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 使用这一定义,你就可以用下面任一种方式调用过程:gjyLinux联盟 gjyLinux联盟 MessBox (\'Something wrong here!\');gjyLinux联盟 gjyLinux联盟 MessBox (\'Something wrong here!\', \'Attention\');gjyLinux联盟 gjyLinux联盟 MessBox (\'Hello\', \'Message\', mb_OK);gjyLinux联盟 gjyLinux联盟 确省参数使用主要规则:调用时你只能从最后一个参数开始进行省略,换句话说,如果你要省略一个参数,你必须省略它后面所有的参数。gjyLinux联盟 gjyLinux联盟 确省参数的使用规则还包括:gjyLinux联盟 gjyLinux联盟 · 带确省值的参数必须放在参数表的最后面。 gjyLinux联盟 gjyLinux联盟 · 确省值必须是常量。显然,这限制了确省参数的数据类型,例如动态数组和界面类型的确省参数值只能是 nil;至于记录类型,则根本不能用作确省参数。 gjyLinux联盟 gjyLinux联盟 · 确省参数必须通过值参或常参传递。引用参数 var不能有缺省值。 gjyLinux联盟 gjyLinux联盟 Q:什么是开放数组参数 ?gjyLinux联盟 gjyLinux联盟 与C语言不同,Pascal 函数及过程的参数个数是预定的。如果参数个数预先没有确定,则需要通过开放数组来实现参数传递。gjyLinux联盟 gjyLinux联盟 一个开放数组参数就是一个固定类型开放数组的元素。 也就是说,参数类型已定义,但是数组中的元素个数是未知数。gjyLinux联盟 gjyLinux联盟 单元的工作空间 gjyLinux联盟 gjyLinux联盟 Pascal单元是封装性和可视性的关键,它很可能比类中的 private 和 public 关键字还要重要。(实际上,private关键字与类单元的工作空间有关)。一个标识符(如一个变量、过程、函数或数据类型)的工作空间是指能访问标识符的代码段。基本原则是:标识符在它工作空间内才有意义,也就是说,只在其声明的代码块中才有意义,在工作空间外你不能访问这些标识符。例如:gjyLinux联盟 gjyLinux联盟 · 局部变量:如果你在例程或方法代码块内声明一个变量,那么单元外部不能访问这个变量。该标识符的工作空间就是定义标识符的整个例程,其中包括嵌套例程(除非嵌套例程内有一个同名标识符覆盖了外部定义)。当调用到例程时,其变量压入栈内存中,例程一结束,栈中的内存就自动释放。 gjyLinux联盟 gjyLinux联盟 · 全程隐藏变量:如果你在单元的实现部分声明一个标识符,那么在单元外你不能使用它,但是能在单元内任一代码块及过程中使用它。程序一启动就会为全程隐藏变量分配内存,程序终止内存释放,你可以在单元初始化区给它赋初值。 gjyLinux联盟 gjyLinux联盟 · 全程变量:如果你在单元的界面部分声明标识符,那么该标识符的工作空间就扩大了,任何Use它的单元都能访问它。这类变量的内存分配及生命周期与上类变量相同,唯一不同的是其可见性。 gjyLinux联盟 gjyLinux联盟 只要程序单元的uses子句中列出某一单元名,那么所列单元界面区中声明的任何标识符该程序都能访问。窗体类的变量就是这样声明的,所以你可以在其他窗体代码中访问这个窗体以及它的公共域、方法、属性和组件。当然把什么都声明为全局标识这种编程习惯并不好。除了明显的内存消耗问题外,使用全程变量使代码维护和更新变得困难。一句话,你应该尽量少用全程变量。gjyLinux联盟 gjyLinux联盟 单元包括界面区(interface)及实现区(implementation),界面区用于声明其它单元能看到的部分;实现区存放界面的实现代码及外部不可见的声明。gjyLinux联盟 gjyLinux联盟 单元总体结构如下:gjyLinux联盟 gjyLinux联盟 unit unitName;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 interfacegjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // other units we need to refer togjyLinux联盟 gjyLinux联盟 usesgjyLinux联盟 gjyLinux联盟 A, B, C;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // exported type definitiongjyLinux联盟 gjyLinux联盟 typegjyLinux联盟 gjyLinux联盟 newType = TypeDefinition;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // exported constantsgjyLinux联盟 gjyLinux联盟 constgjyLinux联盟 gjyLinux联盟 Zero = 0;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // global variablesgjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 Total: Integer;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // list of exported functions and proceduresgjyLinux联盟 gjyLinux联盟 procedure MyProc;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 implementationgjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 usesgjyLinux联盟 gjyLinux联盟 D, E;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // hidden global variablegjyLinux联盟 gjyLinux联盟 vargjyLinux联盟 gjyLinux联盟 PartialTotal: Integer;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 // all the exported functions must be codedgjyLinux联盟 gjyLinux联盟 procedure MyProc;gjyLinux联盟 gjyLinux联盟 begingjyLinux联盟 gjyLinux联盟 // ... code of procedure MyProcgjyLinux联盟 gjyLinux联盟 end;gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 initializationgjyLinux联盟 gjyLinux联盟 // optional initialization partgjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 finalizationgjyLinux联盟 gjyLinux联盟 // optional clean-up codegjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 end.gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 实现区头部的uses子句用于表示只在实现部分访问的单元。如果例程或方法的代码需要引用其他单元,你应该把这些单元加到实现区子句中,而不是界面区。你所引用的单元必须在工程文件目录中能找到,或在工程选项对话框的 Directories/Conditionals 页设定这些单元的搜索路径。gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 gjyLinux联盟 应用程序内存区gjyLinux联盟 gjyLinux联盟 Q:全局内存区,堆,栈之间的区别?gjyLinux联盟 gjyLinux联盟 1,全局变量:gjyLinux联盟 gjyLinux联盟 全程变量内存在程序启动时就分配,然后一直保留到程序终止才释放.gjyLinux联盟 gjyLinux联盟 2,堆:gjyLinux联盟 gjyLinux联盟 堆表示程序可用的内存区,也叫动态内存区。堆内存的分配与释放次序是随机的,这就是说,如果你按次序分配三块内存,那么到时并不按分配时的次序释放内存。 堆管理器会负责所有操作,你只需简单地使用GetMem 函数请求新内存或调用constructor 建立对象, Delphi 会返回一个新的内存块(随意重用已经丢弃的内存块)。 gjyLinux联盟 gjyLinux联盟 堆是应用程序可用的三种内存区之一, 其它两种分别是全局内存区(存放全程变量) 和栈。与堆相反,全程变量内存在程序启动时就分配,然后一直保留到程序终止才释放;栈的内容请详见术语表。 gjyLinux联盟 gjyLinux联盟 Delphi 使用堆为对象、字符串、动态数组及特殊的动态内存请求(GetMem)内存分配。 gjyLinux联盟 gjyLinux联盟 Windows 应用程序的地址空间最大允许有 2 GigaByte, 其中大部分能被堆使用。 gjyLinux联盟 gjyLinux联盟 3,栈:gjyLinux联盟 gjyLinux联盟 栈表示程序可用的内存区,栈内存动态分配,并按特定次序分配、释放。栈内存按后进先出次序(LIFO)分配,这表示最后分配的内存区先被释放。gjyLinux联盟 gjyLinux联盟 栈内存一般在例程中使用(过程、函数及方法调用)。 当你调用例程时,例程参数及返回值是放在栈中的(除非使用Delphi缺省调用方式,对调用过程进行优化)。此外,例程中声明的变量(在begin语句前的 var 块中)也存放在栈中,所以当例程终止时,这些变量会被自动清除(在返回调用点之前以LIFO次序释放)。 gjyLinux联盟 gjyLinux联盟 Delphi 使用栈存放例程参数及其返回值(除非你使用Delphi缺省的 register 调用协定)、局部例程变量、Windows API 函数调用等等。 gjyLinux联盟 gjyLinux联盟 Windows 应用程序可以预留大量的栈内存,在 Delphi 中你可以通过工程选项的 linker 页设置, 不过一般采用缺省设置就可以了。 如果你收到一个栈溢出错误信息,这可能是因为你的函数进入了死循环自调用,而不是栈空间太小。gjyLinux联盟
Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论 |
|
|
|
|
|