Delphi2007新功能 -- 有限的栈对象

今天使用Delphi2007,一个误输入,无意中发现Delphi2007的record类型居然能够和TObject一样定义方法和属性,而且不需要调用类似TObject.Create方法就能生成一个record对象。这是否意味着Delphi2007也能和C++一样,不仅能使用堆对象(new),也能使用栈对象(静态对象)呢?

通过实验,答案是肯定的!这使我感到很兴奋,因为Delphi从诞生之日起,就限定了只能继承于TObject的堆对象,必须通过Create和Free来建立和销毁一个对象,而不能使用栈对象。而栈对象的好处就在于它能和其它类型一样很方便的定义,它能自动调用构造函数和析构函数,在作用域范围内(如函数内的局部对象)不必当心对象的建立和销毁问题。要是Delphi具有了该功能,无意是Delphi编程者们的福音。

不过,进一步的测试却比较失望,请看下面的代码:

type
  TMyRecord = record
  private
    x: Integer;
    y: Integer;
  public
    // error: Parameterless constructors not allowed record types
//    constructor Create;
    // error: A record cannot introduce a destructor
//    destructor TMyRecird;
    constructor Create(a: Integer);
    constructor TMyRecord; overload;
    constructor TMyRecord(a, b: Integer); overload;
//    constructor TMyRecord(a, b: Integer);
    procedure Display;
    property xi: Integer read x;
  end;

{ TMyRecord }

constructor TMyRecord.Create(a: Integer);
begin
  x := a;
  y := 0;
end;

procedure TMyRecord.Display;
begin
  ShowMessage(Format(‘x = %d, y = %d‘, [x, y]));
end;

constructor TMyRecord.TMyRecord;
begin
  x := 0;
  y := 0;
end;

constructor TMyRecord.TMyRecord(a, b: Integer);
begin
  x := a;
  y := b;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  rec: TMyRecord;
begin
  rec.TMyRecord(100, 200);
  rec.Display;
end;
        可以看出,确实可以和C++一样定义一个局部record对象(不需要动态建立),而且可以使用该对象的方法和属性,请看TForm1.Button1Click方法的汇编码(CPU调试窗口粘贴下来的):
Unit1.pas.72: begin
0045ACDC 83C4F8           add esp,-$08
Unit1.pas.73: rec.TMyRecord(100, 200);
0045ACDF 8BC4             mov eax,esp
0045ACE1 B9C8000000       mov ecx,$000000c8
0045ACE6 BA64000000       mov edx,$00000064
0045ACEB E8E4FFFFFF       call TMyRecord.TMyRecord
Unit1.pas.74: rec.Display;
0045ACF0 8BC4             mov eax,esp
0045ACF2 E855FFFFFF       call TMyRecord.Display
Unit1.pas.75: end;
0045ACF7 59               pop ecx
0045ACF8 5A               pop edx
0045ACF9 C3               ret

从汇编码中看,定义的TMyRecord变量rec确实是标准C++栈对象一样的,在调用其方法的时候也隐含传递了Self指针(mov  eax,esp),也就是说,rec在这里已经区别于普通的record变量,而是一个实实在在的“对象”变量!

但是遗憾的是,它不能定义destructor方法,虽然可以定义constructor方法(不能定义为Tobject缺省的Create方法,带参数可以),但却不能在定义的时候自动调用构造方法(我原本以为和C++一样,定义一个和TMyRecord同名的constructor方法,可以自动调用的),如此一来,静态栈对象的主要优点就丧失了,如果手工调用构造方法,和定义一个普通record变量,然后调用静态过程没什么两样了。其实,Delphi已经把record改道这一步了,稍稍进一步就可以完完全全的使用栈对象,从技术上讲一点难度都没有,编译器只需要在栈中分配对象变量内存和销毁对象变量内存的同时,隐含调用一下构造方法和析构方法就可以了的。

虽然很遗憾,但是还是为Delphi的这点进步而高兴,至少我们可以利用这一功能封装record,而且使用这有限的栈对象可以不用当心对象本身的销毁问题(record对象中动态分配的内存还是得手工释放或者调用它的某个方法释放)。

后记:以前在DOS下,以C/C++为主,Pascal只用过Turbo Pascal4.0,对以后Pascal的版本并不十分了解,今天看了网友housisong的留言,才知道我所谓的新功能--有限栈对象,Delphi中早就有了,如Delphi7.0就可以使用Object关键字定义栈对象,而且比2007的record类型还完善一些,record不能继承,而object对象能够继承,看来我真是孤陋寡闻了!!!

时间: 2024-10-16 14:02:12

Delphi2007新功能 -- 有限的栈对象的相关文章

C++——内存对象 禁止产生堆对象 禁止产生栈对象

用C或C++写程序,需要更多地关注内存,这不仅仅是因为内存的分配是否合理直接影响着程序的效率和性能,更为主要的是,当我们操作内存的时候一不小心就会出现问题,而且很多时候,这些问题都是不易发觉的,比如内存泄漏,比如悬挂指针. 我们知道,C++将内存划分为三个逻辑区域:堆.栈和静态存储区.既然如此,我称位于它们之中的对象分别为堆对象,栈对象以及静态对象.那么这些不同的内存对象有什么区别了?堆对象和栈对象各有什么优劣了?如何禁止创建堆对象或栈对象了? 一.基本概念 先来看看栈. 栈,一般用于存放局部变

[VS2010] ADO.NET Entity Framework 新功能:永续保存无知对象 (Persistence-Ignorant Object) Overview

ADO.NET Entity Framework 的新功能:永续保存无知对象.可以说是 Entity Framework 划时代的新功能,颠覆一般的数据组件/DAL 与数据库间的交互方式. 前一篇文章介绍了 ADO.NET Entity Framework 的模型优先设计 (Model First Design) 功能,有没有觉得 .NET Framework 4.0 中的 ADO.NET Entity Framework 进步了很多呢?如果你这样就满足了,那接下来的东西你看了可能会像某啤酒广告

VS2015预览版中的C#6.0 新功能(二)

VS2015预览版中的C#6.0 新功能(一) VS2015预览版中的C#6.0 新功能(三) 自动属性的增强 只读自动属性 以前自动属性必须同时提供setter和getter方法,因而只读属性只能通过先声明field,然后property只提供getter方法来实现,无法通过自动属性来实现.在c#6.0中,可以通过如下的形式声明只读的自动属性: public string FirstName { get; } 对于只读的自动属性,其backing field是readonly的,其值可以在属性

PHP5各个版本的新功能和新特性总结

因为 PHP 那“集百家之长”的蛋疼语法,加上社区氛围不好,很多人对新版本,新特征并无兴趣.本文将会介绍自 PHP5.2 起,直至 PHP5.6 中增加的新特征 本文目录:PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束PHP5.2:JSON 支持PHP5.3:弃用的功能,匿名函数,新增魔术方法,命名空间,后期静态绑定,Heredoc 和 Nowdoc, const, 三元运算符,PharPHP5.4:Short Open Tag, 数组简写形式,Traits, 内置

PHP 5.2、5.3、5.4、5.5、5.6 版本区别对比以及新功能详解

截至目前(2015.1), PHP 的最新稳定版本是 PHP5.5, 但有差不多一半的用户仍在使用已经不在维护  的 PHP5.2, 其余的一半用户在使用 PHP5.3 .因为 PHP 那"集百家之长"的蛋疼语法,加上社区氛围不好,很多人对新版本,新特征并无兴趣.本文将会介绍自 PHP5.2 起,直至 PHP5.6 中增加的新特征. PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束 PHP5.2:JSON 支持 PHP5.3:弃用的功能,匿名函数,新增魔术方

Docker 1.12.0将要发布的新功能

导读 按计划,6/14 是1.12.0版本的 feature冻结 的日子,再有两个星期Docker 1.12.0也该发布了.这里列出来的新功能,都是已经合并到主分支的功能,不出意外,下一个版本的Docker应该是能体验到了. 下周2016 DockerCon也该开始了,好像也有一场专门来讲Docker新特性的,不过在这之前,我们就可以抢先一步,浏览一下这些新功能.新特性.尤其是前两个,都是比较吸引人的功能. Swarmkit集成 前几天Docker刚刚发布了 Swarmkit ,也就是Swarm

REDGATE SQLPROMPT 6.0新功能

原文:REDGATE SQLPROMPT 6.0新功能 REDGATE SQLPROMPT 6.0新功能 下载地址:http://files.cnblogs.com/lyhabc/SQLPrompt6.02013-11-2.rar (1)自动刷新代码提示,当数据库中有对象更改过之后马上可以看到更改后的内容 (2)tab窗口改变颜色(由数据库操作者自己设置颜色,用来提醒自己当前他自己所操作的数据库是在什么环境下) 注意:这个功能是自己手动设置的不是自动的(这个功能只适用于SQLSERVER2012

05-TypeScript中的方法新功能(下)

再TypeScript中,方法还有一些新功能能够让我们更好的控制方法执行. 1.Generator方法: yield关键字用于控制方法在执行的时候暂停住,后续方法调用方又可以从暂停的地方继续执行,这种具有yield关键字的并标记为*的方法叫Generator方法. function* dosomething(){ console.log("starting"); // 执行到这里,会暂停住 yield ; console.log("finished"); } var

看了一下unity5.6的新功能 以及Timeline

3月31日unity5.6发布,然而timeline(前sequence模块)被delay到unity 2017.上个星期官方又发布了unity 2017的beta版本 有一阵子没写博客了,写一篇整理归纳 1.Physics Debugger 用于可视化调试场景中的物理组件,其中Hide系列开关都是针对特殊高亮的 他只会隐藏高亮,而不会真正隐藏对象. 2.Test Runner集成播放模式测试 这个之前的单元测试插件就有,叫做集成测试,不过很不好用. 大概感觉是有一些改动,对比一下: 新版本(E