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 ...
随机推荐
- 1.offsetParent,offsetLeft,offsetTop
offsetParent <!doctype html> <html> <head> <meta charset="utf-8"> ...
- VS2008 自定义向导的default.js设置(DLL文件)
function OnFinish(selProj, selObj) { try { var strProjectPath = wizard.FindSymbol('PROJECT_PATH'); v ...
- PHP学习日记(一)——类、函数的使用
一.自定义函数 function add($a,$b){ $c=$a+$b; echo 'add test:'; echo $c; return $c; } add(1,2); 输出结果: add t ...
- EditText 空指针问题
今天在Android中碰到了这样一个问题,其实应该很少人会碰到,因为只有像我这种奇葩才会犯这种错误. 但既然解决了,我就想在这里跟大家分享一下,毕竟它困扰了我一个白天啊...不多说了,看下面... 其 ...
- [WPF]解决ListView在没有Items时,水平滚动条不出现的问题
转载地址:http://www.cnblogs.com/nankezhishi/archive/2010/03/19/FixListViewNotScrollHeaderBug.html 在上一篇Bl ...
- Android - Ant自动编译打包android项目 -- 1(转)
1. 背景: Eclipse用起来虽然方便,但是编译打包android项目还是比较慢,尤其当要将应用打包发布到各个渠道时,用Eclipse手动打包各种渠道包就有点不切实际了,这时候我们用到Ant帮我 ...
- eclipse中的两种Jre 及 Jre与Jdk的区别
分类: ——————————区分eclipse中的两种Jre———————- (Eclipse也是一个普通的Java程序,因此必须有一个JRE做为运行环境.如果你的机器上没有安装任何JRE(或者JDK ...
- POJ——放苹果
4:放苹果 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示) ...
- JavaScript js生成GUID
function generateUUID(){ var d = new Date().getTime(); var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxx ...
- iterm快捷键及操作技巧(附Linux快捷键)
标签操作 新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 command + 左右方向键 切换全屏:command + enter 查找:com ...