delphi project of object

http://www.cnblogs.com/ywangzi/archive/2012/08/28/2659811.html

其实要了解这些东西,适当的学些反汇编,WINDOWS内存管理机制,PE结构,看下李维的VCL架构剖析可以很好理解
type
  TMyEvent = procedure of object;
这是一种数据类型的定义,他定义了一个可以在类中使用的函数类型
区别于
type
  TMyProc = procedure;

TMyEvent 和 TMyProc 都定义了一个函数类型,他们的差别是,TMyProc 不可以用在类中定义事件,TMyEvent 却可以。

如果你想知道问什么,那就需要深入了解事件类型以及函数类型到底是个什么?

procedure a();
begin
  ShowMessage()
end;

var
  Func1: TMyProc;
  Func2: TMyEvent;

func1 := A;

func1 := A;

这句到底发生了什么事情呢?

在32位的windows操作系统中,任何一个进程被执行,操作系统要完成的工作基本上包括:为这个进程开辟一个线性的虚拟地址表(从$00000000到$FFFFFFFF),然后把exe程序加载到这个地址表对应的内存中,然后跳入到exe程序的入口点,剩下的事情,就是exe自己从入口点开始一步一步干自己的事情了。
程序中,所有的函数都被编译到固定的位置,也就是每个函数都有一个地址与之对应,对函数的调用,实际上就是在寄存器或者堆栈中准备好参数,然后跳入到函数对应的地址继续执行。
func1 := A;
这个动作,完成的就是把函数A的地址赋值给func1这个变量。

那么,为Func2: TMyEvent 赋值又是完成了什么呢?

类中的函数也是有地址的,编译后,类中的函数也会被编译到一个固定的地址上。
但是,func2不是表示一个函数地址,他是一个记录类型的变量
这个可以通过 SizeOf(TMyEvent) 看到 SizeOf(TMyEvent) 返回值是8,而SizeOf(TMyProc)返回的是4
实际上,TMyEvent类型是包含两个域的一个记录,其中一个域是Code,也就是和TMyProc一样的,另一个域是Data,他保存着一个对象。

Button2.OnClick := Button1Click;
这样的赋值,实际上是将窗体类的对象form1给data域,将Button1Click这个函数的地址给Code域
 
 
 
 
 
 
 
1.
TMyEvent = procedure of object; TMyEvent 是方法类型 就等于 String 是一种数据类型

如在一个Txxx类中定义了一个过程  
procedure Txxx.test;
begin
  showmessage(‘1‘);
end;

那么就可以把 Txxx.test 赋给 TMyEvent 了 (TMyEvent := Txxx.test);
因为 TMyEvent 的定义中有 of object 所以赋值给它的只能是类中的过程,而不能是普通过程。

2.
FOnHundred: TMyEvent; --> FOnHundred 是一个变量 它的类型是 TMyEvent,  
  就等于 icount : integer 这么简单

3.
property OnHundred: TMyEvent read FOnHundred write FOnHundred

OnHundred 是一个属性 它的类型也是 TMyEvent 通过 FOnHundred 变量来存取 这个属性的值。

当属性不用过程去存取的时候 (如上例)调用 OnHundred 和 FOnHundred 是相同的

delphi中经常见到以下两种定义

Type

TMouseProc = procedure (X,Y:integer);

TMouseEvent = procedure (X,Y:integer) of Object;

两者样子差不多但实际意义却不一样,

TMouseProc只是单一的函数指针类型;

TMouseEvent是对象的函数指针,也就是对象/类的函数/方法

区别在于类方法存在一个隐藏参数self,也就是说两者形参不一样,所以不能相互转换。

这也就是为什么delphi中可以这样赋值 button1.onClick:=button2.onClick;

却不能这样赋值 button1.onclick=buttonclick; (buttonclick为本地函数,button2.onclick为类方法)的原因!

方法类型定义:TMethod = procedure of object;

Procedural types allow you to treat procedures and functions as values that can be assigned to variables or passed to other procedures and functions. For example, suppose you define a function called Calc that takes two integer parameters and returns an integer:

function Calc(X,Y: Integer): Integer;

You can assign the Calc function to the variable F:

var F: function(X,Y: Integer): Integer;

F := Calc;

If you take any procedure or function heading and remove the identifier after the word procedure or function, what’s left is the name of a procedural type. You can use such type names directly in variable declarations (as in the example above) or to declare new types:

Type

TIntegerFunction = function: Integer;

TProcedure = procedure;

TStrProc = procedure(const S: string);

TMathFunc = function(X: Double): Double;

Var

F: TIntegerFunction;{ F is a parameterless function that returns an integer }

Proc: TProcedure;   { Proc is a parameterless procedure }

SP: TStrProc;       { SP is a procedure that takes a string parameter }

M: TMathFunc;       { M is a function that takes a Double (real) parameterand returns a Double }

procedure FuncProc(P: TIntegerFunction);  { FuncProc is a procedure whose only parameter is a parameterless integer-valued function }

The variables above are all procedure pointers—that is, pointers to the address of a procedure or function. If you want to reference a method of an instance object (see Classes and objects), you need to add the words of object to the procedural type name. For example

Type

TMethod = procedure of object;

TNotifyEvent = procedure(Sender: TObject) of object;

These types represent method pointers. A method pointer is really a pair of pointers; the first stores the address of a method, and the second stores a reference to the object the method belongs to. Given the declarations

Type

TNotifyEvent = procedure(Sender: TObject) of object;

TMainForm = class(TForm)

procedure ButtonClick(Sender: TObject);

...

end;

var

MainForm: TMainForm;

OnClick: TNotifyEvent

we could make the following assignment.OnClick := MainForm.ButtonClick;

Two procedural types are compatible if they have the same calling convention,the same return value (or no return value), and the same number of parameters, with identically typed parameters in corresponding positions. (Parameter names do not matter.)

Procedure pointer types are always incompatible with method pointer types. The value nil can be assigned to any procedural type.

Nested procedures and functions (routines declared within other routines) cannot be used as procedural values, nor can predefined procedures and functions. If you want to use a predefined routine like Length as a procedural value, write a wrapper for it:

function FLength(S: string): Integer;

begin

Result := Length(S);

end;

时间: 2024-10-10 04:56:14

delphi project of object的相关文章

Advanced Features of Delphi DLLs

http://www.delphisources.ru/pages/faq/master-delphi-7/content/LiB0104.html Beside this introductory example, you can do a few extra things with dynamic libraries in Delphi. You can use some new compiler directives to affect the name of the library, y

Delphi中的文件扩展名

Filename Extensions in Delphi http://delphi.about.com/od/beginners/a/aa032800a.htm Try building a small test project ... whoa ... a typical Delphi application consists of many different file types. Delphi employs a number of files for its configurati

Delphi资源大全

A curated list of awesome Delphi frameworks, libraries, resources, and shiny things. Inspired by awesome-... stuff. Note that only open-source projects are considered. Dead projects are mainly ignored except for those which do not have alive analogs.

Delphi编程OOP思想【转】

原文:http://blog.sina.com.cn/s/blog_9c47a15201015rew.html 注:本文摘自http://blog.csdn.net/haiou327/article/details/5937171,转载请注明: 好东西大家分享 刚刚接触的Delphi的朋友,可能最感兴趣的就是它丰富.强大的VCL(可视化构件库).仅仅向窗体上扔几个构件,甚至不用动手写代码,就能很容易地做出一个有实用价值的程序,真是令人激动.但是,VCL只是Delphi的一小部分,Delphi的优

第三章 传奇的开始--Delphi(附读书笔记)

第三章 传奇的开始--Delphi "是惊世之作的Delphi让Borland重新站了起来,没有当初的Delphi,就没有今日的Borland!" "是Turbo Pascal诞生了Borland,但却是Object Pascal给予了Borland重生的机会!" 创造传奇故事的主角--Delphi 没有人会知道在两年后Borland C/C++会遭遇到这么大的失败,也没有人会预料到Borland又会再次因为Pascal而东山再起.Borland奋斗史精彩的地方就在

Delphi开发中各种文件扩展名代表什么文件

暂时就遇到了以下这几种,以后遇到再进行补充 .DPR Delphi Project文件,包含了Pascal代码 .PAS Pascal文件,Pascal单元的源代码,可以是与窗体有关的单元或是独立的单元. .DFM Delphi Form File,描述窗体或数据模块及其组件属性的二进制文件. .DCU Delphi Compiled Unit.编译结果. .RES 资源文件. .BPL Borland Package Library.包含Delphi环境在设计时或应用程序在运行时使用的VCL组

Delphi 项目 结构 文件夹 组织

Delphi Project Structure Folder Organization http://delphi.about.com/od/delphitips2008/qt/project_layout.htm I've been developing in Delphi for the past 10+ years (from Delphi 1). Every version brings some new features - new controls, new build optio

delphi中的.dpr、.pas和.dfm文件都怎么解释?

.dpr..pas和.dfm文件都是什么意思啊,有什么区别? DPR: Delphi Project文件,包含了Pascal代码. PAS: Pascal文件,Pascal单元的源代码,可以是与窗体有关的单元或是独立的单元. DFM:Delphi Form File,描述窗体或数据模块及其组件属性的二进制文件. =========================================================其他相关: 扩展名 英文解释 文件内容HWezBPG Borland P

Delphi项目构成之项目文件DPR

一个Delphi项目(Delphi Project)由若干个相关文件构成.一些文件时在设计时创建,还有一些是在编译项目的时候生成的.要有效的管理Delphi项目(Delphi Project),就必须知道每个文件的用途. 下面我先来熟悉下项目文件(The Project File),项目文件是在设计时创建的,它的扩展名是.dpr.这个文件也是程序的主文件. Delphi项目的各个文件必须遵守预定义格式,这样编译器才能读懂单元,并把它编译成单元代码. 下面我来看看如何查看缺省Delphi项目的项目