delphi高手突破学习笔记之面向对象类和对象的本质
知识点1:堆和栈
每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack)。
堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的。例如,用GetMem函数获取了一定大小的内存空间,则在使用完后,必须调用FreeMem函数将空间释放,否则就会发生所谓的“内存泄漏”。“借债还钱,天经地义”。
栈又称为“自动存储区”,其中的内存空间的分配与释放是由编译器和系统自动完成的,不需要程序员过问。函数调用时按值传递的参数所占空间、函数中的局部变量等,都是在栈中被分配空间的。比如函数:
|
1
|
var i : Integer; j : Integer; begin for i := 1 to 10 do ...... ...... end; |
其中,i和j的空间是由编译器在栈中分配的。在函数末尾,也不需要程序员手动去释放这两个变量所占的内存空间。
Objecgt Pascal遵循所谓的“引用/值”模型。无论在参数传递还是变量定义中,简单类型(如Integer、Cardinal、char以及record等)被按值传递或使用,其内存空间从栈中分配。
而复杂类型(class)则被按引用传递或使用,其内存空间从堆中分配。在Object Pascal中,所有对象(类类型的)都被建立在内存的堆空间上,而非栈上。因此在创建对象时,其构造函数不会被编译器自动调用,也没有C++中所谓的“默认构造函数”。调用构造函数来创建对象以及调用析构函数来消灭对象都是程序员的职责。
知识点2:构造函数与对象内存的分配
定义构造函数使用Constructor关键字。按惯例,构造函数名称为Create(当然也可以用其他名称,但那绝非优良的设计)。要创建出一个对象,首先需要分配对象本身所占用的内存空间,然后执行类的构造函数,以初始化各数据成员、申请对象需要的资源或创建其内部包含的子对象。编译器在执行类似MyFamilyObject := TMyFamily.Create(‘Zhang’, ‘Li’);这样的构造函数之前,会插入以下几行汇编代码:
|
1
|
test dl, dl jz +$08 add esp, -$10 call @ClassCreate // 注意这行代码 |
以上代码的最后一行代码调用的是system.pas文件的第8949行的_ClassCreate函数。内存分配完成后是调用类的构造函数,即TMyClass.Create(),以初始化数据成员。构造函数由定义类的程序员编写,也就是说,将对象初始化成何种模样是由程序员决定的。至此,一个对象已经诞生了。之后,编译器会再插入以下几行汇编代码:
|
1
|
test dl, dl jz +$0f call @AfterConstruction pop dword ptr fs:[$00000000] add esp, $0c |
构造函数的职责只是初始化对象的数据成员,没有构造函数只意味着不会对数据成员进行初始化而已,编译器会对所有数据进行清零初始化。
知识点3:析构函数与对象内存的回收
定义析构函数使用Destructor关键字。按惯例,析构函数名称为Destroy。
|
1
|
type TMyClass = class Public Destructor Destroy(); override; End; |
在析构对象的时候,应该调用对象的Free()方法而不是直接调用Destroy()。
这是因为,在TObject的Free()方法中会判断对象本身是否为nil,如果不为nil则调用对象的Destroy(),以增加安全性。既然有这样更安全的做法,当然没有理由不这么做了。
永远不要直接调用对象的Destroy(),而应该是Free()。
知识点4:实例介绍
|
1
|
unit DllLoader; interface uses windows; Type TDllLoader = class Protected // 之所以是protected成员,是为了在其派生类中具体实现加载某DLL时,派生类 能够访问该句柄 FhDLL : HMODULE; Public Constructor Create(strDLLName : String); Destroctor Destroy(); override; End; Implementation Constructor TDllLoader.Create(strDLLName : String); Begin FhDLL := LoadLibrary(strDLLName); // 构造函数中加载DLL ASSERT(FhDLL <> 0); End; Destructor TDllLoader.Destroy(); Begin If FhDLL <> 0 then begin FreeLibrary(FhDLL); // 析构函数中释放DLL FhDLL := 0; End; End; End. |
知识点5:“类方法”与“类引用”类型
一般所称的“方法”,都是指“对象方法”。也就是说,执行该方法,将可能导致对象的状态发生改变,即该方法可以更改对象的数据成员的值。如:
|
1
|
TMyClass2 = class private FMember : Integer; pubic procedure SetValue(Value : Integer); end; procedure TMyClass2.SetValue(Value : Integer); begin FMember := Value; end; |
其中SetValue即为典型的对象方法。
除了“对象方法”外,还有所谓的“类方法”,也就是属于类级别的函数(而非对象级别的)。它可以改变类的状态(而非对象的状态)。
定义类方法,只需要在一般的方法声明前加上class关键字。如:
|
1
|
class function TObject.ClassName: ShortString; |
既然类方法是进行类级别的操作,因此在类方法中是无法对对象的数据成员进行访问的。以下的代码展示了类方法中self的使用方法:
|
1
|
interface Type TClassMethodExample = class |
|
1
|
private FnInteger : Integer; public class function ClassMethod1() : Integer; class function ClassMethod2() : Integer; function Method() : Integer; end; implementation { TClassMethodExample } class function TClassMethodExample.ClassMethod1: Integer; begin self.Method() ; // 非法,因为Method不是类方法 self.ClassMethod2(); // 合法 end; class function TClassMethodExample.ClassMethod2: Integer; begin Result := self.nInteger; // 非法,类方法中不能访问对象数据成员 end; function TClassMethodExample.Method: Integer; begin Result := 0; end; end.
|
http://www.vckbase.com/module/articleContent.php?id=4384
delphi高手突破学习笔记之面向对象类和对象的本质的更多相关文章
- delphi高手突破学习笔记之面向对象类和对象的本质(有汇编解释 good)
知识点1:堆和栈 每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack). 堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的.例如,用GetMem函数获取了一 ...
- python cookbook第三版学习笔记十:类和对象(一)
类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair: def __init__(self,x,y): self.x=x self. ...
- [javase学习笔记]-6.2 类与对象的关系
这一节我们来看一下类与对象之间的关系. 我们学习java语言,目的就是用java语言对现实生活中的事物进行描写叙述.那么我们如何来描写叙述呢.这就引出了类,我们在实际实现时,是通过类的形式来体现的. ...
- delphi VCL研究之消息分发机制-delphi高手突破读书笔记
1.VCL 概貌 先看一下VCL类图的主要分支,如图4.1所示.在图中可以看到,TObject是VCL的祖先类,这也是Object Pascal语言所规定的.但实际上,TObject以及TObject ...
- java学习-初级入门-面向对象⑥-类与对象-静态static
这次我们来学习静态(static) 知识点 1.静态方法只能调用静态变量 2.静态变量属于整个Class,会随着发生变化. 案例:定义一个自动增长的学生类. 题目要求: 定义一个学生类,除了姓名.性别 ...
- python cookbook第三版学习笔记十三:类和对象(三)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...
- ES6学习笔记四(类和对象)
{ // 构造函数和实例 class Parent{ constructor(name='mukewan'){ this.name=name; } } let v_parent=new Parent( ...
- python cookbook第三版学习笔记十三:类和对象(四)描述器
__get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...
- python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法
在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object): def spam(self): print 'A.spam' class ...
随机推荐
- 关于lvs+keepalived只加入一台realserver问题
今天做lvs+keepalived+mysql项目实施方案,在配置lvs+keepalived时都是ok的,但是就只加入第一台realserver.本人也感到很奇怪,lvs+keepalived本人也 ...
- 有了bootstrap,为什么还要做amaze ui
1.Bootstrap介绍Bootstrap,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加 ...
- web2py官方文档翻译
00前言 我相信能够轻松地构建高质量增长的web应用程序是至关重要的一个自由和开放的社会.这可以防止玩家最大的垄断信息的流通. 因此我从2007年开始web2py项目,主要是作为一种教学工具与简化we ...
- 动态创建分页 LINQ+EF
public class Message { public int MessageId { get; set; } public string MessageTitle { get; set; } p ...
- Delphi SysErrorMessage 函数和系统错误信息表
在看 API 文档时, 我们经常见到 GetLastError; 它可以返回操作后系统给的提示. 但 GetLastError 返回的只是一个信息代码, 如何返回对应的具体信息呢? FormatMes ...
- Facebook有两名重要经理离职 有一位将加入阿里
据报道,Facebook将有两名重要经理离职,分别是领导视频广告产品的产品经理和企业沟通团队经理. 这是该仍在迅速增长的公司最新的人员离职情况.Facebook计划今年大幅扩张人员规模. 知情人士称, ...
- HM中CU,TU的划分
相信只要是做算法改进的,首先都会遇到这么一个问题:CU,PU及TU这几个在HM中该如何打印出它们最终的划分情况呢?也经常有人来问我这个问题,一般来说,因为问我的时候我一般手头都没有现成的代码可以提供, ...
- Apache HTTP Server
下载 http://rj.baidu.com/soft/detail/14824.html?ald 安装完成后,打开浏览器,输入http://localhost/ 如果显示: It works! 则代 ...
- 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。
题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解法一:暴力求解.从1开始查找M,然后判断M*N=X这个数字是否只含有0,1. 解法二:由 ...
- linux 命令之 uptime
uptime 命令是用来查询linux系统负载的. 命令格式 uptime [OPTION] -V 显示版本号 不带參数的 uptime 直接输出系统负载. 何为系统负载呢? 系统平均负载被定义为在特 ...