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 ...
 
随机推荐
- mysql学习(十)多表查询
			
多表查询时,要给表名起别名,给字段名其别名(当两个表含有重复字段时) select p.name, c.name, pid from products p, cats c;//得到的结果为笛卡尔乘积 ...
 - phpcms 一些bug
			
首页禁止使用{php $a = }; 因为phpcms在模板解析中默认用到了$a变量,如再次使用会导致phpcms的get标签return报错
 - Laravel中的队列处理
			
Laravel中的队列处理 队列介绍 为什么要有消息队?这里先对其进行一个简单的介绍,方便还不了解的同学理解.在面向对象里,有一个很简单的概念--消息传递,而消息队列就可以在它上面扩展一下,把它说的更 ...
 - 14-利用SVD简化数据
			
参考:http://blog.csdn.net/geekmanong/article/details/50494936 http://www.2cto.com/kf/201503/383087.htm ...
 - 指定端口号,多线程扫描局域网内IP地址
			
小白第一次发博客,请各路大神不要喷,有错的地方还请不吝啬指教,谢谢....... 因为注释基本上已经说清楚啦,在这里就不多说什么啦,知识不够怕误人子弟 # -*- coding:utf-8 -*-im ...
 - js自定义类和对象及继承
			
1.工厂方式 <script type="text/javascript"> function createObject(name){ var p = new Obje ...
 - 使用SndPlaySound从内存中播放WAV
			
有些时候,我们写的程序需要播放音乐,一般大家会采用以下几种方式:1.把音乐文件放置在某个特定的目录,例如Sound,WAV,Music供程序读取播放:2.使用资源来存放音乐.有些人估计也是使用这个方法 ...
 - 表格无边框,有内框,在table嵌套时,防止出现重复边线
			
<html> <head> <title>test 表格无边框,有内框! ^^ CSDN 学习积累</title> <style type=&qu ...
 - 第52周二Restful
			
今天去spring官网发现一个关键词:Restful,以前只在与一个系统对接时用到过这种形式的接口,但印象不深,百度搜索后才感觉自己太out了,这个概念2000年提出,2009年时国内就有很多人推荐使 ...
 - C语言中的回调函数
			
C语言中通过函数指针实现回调函数(Callback Function) ====== 首先使用typedef定义回调函数类型 ====== typedef void (*event_cb_t)(co ...