知识点1:堆和栈

每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack)。

堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的。例如,用GetMem函数获取了一定大小的内存空间,则在使用完后,必须调用FreeMem函数将空间释放,否则就会发生所谓的“内存泄漏”。“借债还钱,天经地义”。

栈又称为“自动存储区”,其中的内存空间的分配与释放是由编译器和系统自动完成的,不需要程序员过问。函数调用时按值传递的参数所占空间、函数中的局部变量等,都是在栈中被分配空间的。比如函数:

  1. var
  2. i : Integer;
  3. j : Integer;
  4. begin
  5. for i := 1 to 10 do
  6. ......
  7. ......
  8. 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
  2. jz +$08
  3. add esp, -$10
  4. call @ClassCreate // 注意这行代码

以上代码的最后一行代码调用的是system.pas文件的第8949行的_ClassCreate函数。内存分配完成后是调用类的构造函数,即TMyClass.Create(),以初始化数据成员。构造函数由定义类的程序员编写,也就是说,将对象初始化成何种模样是由程序员决定的。至此,一个对象已经诞生了。之后,编译器会再插入以下几行汇编代码:

  1. test dl, dl
  2. jz +$0f
  3. call @AfterConstruction
  4. pop dword ptr fs:[$00000000]
  5. add esp, $0c

构造函数的职责只是初始化对象的数据成员,没有构造函数只意味着不会对数据成员进行初始化而已,编译器会对所有数据进行清零初始化。

知识点3:析构函数与对象内存的回收

定义析构函数使用Destructor关键字。按惯例,析构函数名称为Destroy。

  1. type
  2. TMyClass = class
  3. Public
  4. Destructor Destroy(); override;
  5. End;

在析构对象的时候,应该调用对象的Free()方法而不是直接调用Destroy()。

这是因为,在TObject的Free()方法中会判断对象本身是否为nil,如果不为nil则调用对象的Destroy(),以增加安全性。既然有这样更安全的做法,当然没有理由不这么做了。

永远不要直接调用对象的Destroy(),而应该是Free()。
知识点4:实例介绍

  1. unit DllLoader;
  2. interface
  3. uses windows;
  4. Type
  5. TDllLoader = class
  6. Protected
  7. // 之所以是protected成员,是为了在其派生类中具体实现加载某DLL时,派生类 能够访问该句柄
  8. FhDLL : HMODULE;
  9. Public
  10. Constructor Create(strDLLName : String);
  11. Destroctor Destroy(); override;
  12. End;
  13. Implementation
  14. Constructor TDllLoader.Create(strDLLName : String);
  15. Begin
  16. FhDLL := LoadLibrary(strDLLName); // 构造函数中加载DLL
  17. ASSERT(FhDLL <> 0);
  18. End;
  19. Destructor TDllLoader.Destroy();
  20. Begin
  21. If FhDLL <> 0 then
  22. begin
  23. FreeLibrary(FhDLL); // 析构函数中释放DLL
  24. FhDLL := 0;
  25. End;
  26. End;
  27. End.

知识点5:“类方法”与“类引用”类型

一般所称的“方法”,都是指“对象方法”。也就是说,执行该方法,将可能导致对象的状态发生改变,即该方法可以更改对象的数据成员的值。如:

  1. TMyClass2 = class
  2. private
  3. FMember : Integer;
  4. pubic
  5. procedure SetValue(Value : Integer);
  6. end;
  7. procedure TMyClass2.SetValue(Value : Integer);
  8. begin
  9. FMember := Value;
  10. end;

其中SetValue即为典型的对象方法。
除了“对象方法”外,还有所谓的“类方法”,也就是属于类级别的函数(而非对象级别的)。它可以改变类的状态(而非对象的状态)。
定义类方法,只需要在一般的方法声明前加上class关键字。如:

  1. class function TObject.ClassName: ShortString;

既然类方法是进行类级别的操作,因此在类方法中是无法对对象的数据成员进行访问的。以下的代码展示了类方法中self的使用方法:

  1. interface
  2. Type
  3. TClassMethodExample = class
    1. private
    2. FnInteger : Integer;
    3. public
    4. class function ClassMethod1() : Integer;
    5. class function ClassMethod2() : Integer;
    6. function Method() : Integer;
    7. end;
    8. implementation
    9. { TClassMethodExample }
    10. class function TClassMethodExample.ClassMethod1: Integer;
    11. begin
    12. self.Method() ; // 非法,因为Method不是类方法
    13. self.ClassMethod2(); // 合法
    14. end;
    15. class function TClassMethodExample.ClassMethod2: Integer;
    16. begin
    17. Result := self.nInteger; // 非法,类方法中不能访问对象数据成员
    18. end;
    19. function TClassMethodExample.Method: Integer;
    20. begin
    21. Result := 0;
    22. end;
    23. end.

http://blog.csdn.net/sushengmiyan/article/details/7506310

delphi高手突破学习笔记之面向对象类和对象的本质(有汇编解释 good)的更多相关文章

  1. delphi高手突破学习笔记之面向对象类和对象的本质

    知识点1:堆和栈 每个应用程序可以获得的内存空间分为两种:堆(heap)和栈(stack). 堆又称为“自由存储区”,其中的内存空间的分配与释放是必须由程序员来控制的.例如,用GetMem函数获取了一 ...

  2. python cookbook第三版学习笔记十:类和对象(一)

    类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair:     def __init__(self,x,y):         self.x=x         self. ...

  3. [javase学习笔记]-6.2 类与对象的关系

    这一节我们来看一下类与对象之间的关系. 我们学习java语言,目的就是用java语言对现实生活中的事物进行描写叙述.那么我们如何来描写叙述呢.这就引出了类,我们在实际实现时,是通过类的形式来体现的. ...

  4. delphi VCL研究之消息分发机制-delphi高手突破读书笔记

    1.VCL 概貌 先看一下VCL类图的主要分支,如图4.1所示.在图中可以看到,TObject是VCL的祖先类,这也是Object Pascal语言所规定的.但实际上,TObject以及TObject ...

  5. java学习-初级入门-面向对象⑥-类与对象-静态static

    这次我们来学习静态(static) 知识点 1.静态方法只能调用静态变量 2.静态变量属于整个Class,会随着发生变化. 案例:定义一个自动增长的学生类. 题目要求: 定义一个学生类,除了姓名.性别 ...

  6. python cookbook第三版学习笔记十三:类和对象(三)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  7. ES6学习笔记四(类和对象)

    { // 构造函数和实例 class Parent{ constructor(name='mukewan'){ this.name=name; } } let v_parent=new Parent( ...

  8. python cookbook第三版学习笔记十三:类和对象(四)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  9. python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法

    在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object):     def spam(self):         print 'A.spam' class ...

随机推荐

  1. ASP.NET MVC5 学习笔记-2 Razor

    1. Razor @*注释*@ 你在用 @Request.Browser.Browser, 发送邮件给support@qq.com, 转义@@qq @{ var amounts = new List& ...

  2. service and intentservice

    Service是Android中四大组件之一,在Android开发中起到非常重要的作用,先来看一下官方对Service的定义: A Service is an application componen ...

  3. perl学习(4) 子程序

    子程序,类比c语言中的函数,在形式上个人认为最大的区别:没有形参 1.1.定义子程序 1.2.调用 #! /usr/bin/perl sub marine { $n += 1 ; print &quo ...

  4. 数据结构——二叉树(Binary Trees)

    非线性数据结构 二叉搜索树(Binary Search Tree) 树的密度=结点数/高度 二叉树类 #pragma once class stnode { public: int nodeValue ...

  5. CUDA samples 2.3节 用CUDA示例来创建CUDA项目

    2.3.1. Creating CUDA Projects for Windows 略 2.3.2  Creating CUDA Projects for Linux 默认的samples的安装路径 ...

  6. android 上传文件

    android对于上传文件,还是非常easy的,和java里面的上传都是一样的,基本上都是熟悉操作输出流和输入流!另一个特别重要的就是须要一些content-type这些參数的配置!  假设这些都弄好 ...

  7. HDU 4825 Xor Sum 字典树+位运算

    点击打开链接 Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) ...

  8. CKEditor和CKFinder整合实现上传下载功能

    CKEditor与CKFinder整合并实现文件上传功能 事先说明:此整合的是java版本号的, 用到的有:jsp + ckeditor + ckfinder (没有servlet 及其他框架技术) ...

  9. DataTable 用linq分组查询

    DataRow drt = null; var tlist = dt.Select("Atmbs LIKE '%" + d["Two_Code"] + &quo ...

  10. ios中利用NSDateComponents、NSDate、NSCalendar判断当前时间是否在一天的某个时间段内。

    应用中设置一般会存在这样的设置,如夜间勿扰模式,从8:00-23:00,此时如何判断当前时间是否在该时间段内.难点主要在于如何用NSDate生成一个8:00的时间和23:00的时间,然后用当前的时间跟 ...