一、Delphi永远没办法在栈上创建一个对象

下面是一段常见的的Delphi代码,在过程的开头声明本过程所需要的全部局部变量:

procedure Foo;
var
obj: TObject; //这句容易被C++程序员误会。
begin
...
end;

C++程序员会以为obj这个变量就是TObject对象实例本身,会以为这一句是在栈上声明并构造了TObject类的一个对象实例,他们会与下面的C++代码混淆:

void Foo() {     CObject obj; //这一句的确在栈上构造了CObject类的
... //一个对象实例,并且将在离开Foo函数时自动析构它
}

牢记一点,在Delphi里,永远不可能在栈上构造一个对象,也永远不可能对一个对象进行值传递,程序员能看到的是“指向对象实例的指针”,简单地说“一切皆指针”,上例中obj其实就是一个“TObject类型的指针”,当它在栈上被声明的时候,它的值不可知(与C++一样),也没有任何对象被构造出来。上述代码翻译成C++,基本上就是:

void Foo() {
CObject * obj; // 声明一个CObject类型的指针
// 但没有任何对象被构造或与之关联
...
}

作为一个佐证,在Delphi里,sizeof(TObject), sizeof(Self), sizeof(obj) 结果都是4,即一个32位指针的大小。


二、Delphi的构造函数更象是个类方法(静态成员函数)

由于Delphi不允许在栈上构造对象,那么对象实例就只能创建在堆上,Delphi没有new关键字(倒有一个名为New的procedure),而是用一种有别于C++的语法来(在堆上)构造对象:

procedure Foo;
var
obj: TObject; //obj本质上只是一个TObject类型的指针
begin
obj := TObject.Create; //在堆上构造一个TObject对象实例并将其地址赋值给obj
obj.Free; //令obj指向的对象析构
end;

与C++一样,在堆上构造的函数不会在离开作用域的时候被自动析构,所以在离开Foo这个过程之些,要调用TObject的Free方法来析构它。Free方法会调用Destroy析构函数,只不过在调用Destroy之前会判断Self是否为空,如果为空就直接返回。Delphi里的Self,就是C++里的this。

Delphi是单根继承,所有类都从TObject派生而来,而所有类的构造函数一定名为Create,而析构函数一定名为Destroy,当然,析构函数肯定是虚函数。

从声明的形式上看,Create方法象是一个成员函数,但从使用上看,它更象一个类方法(C++里叫静态成员函数),因为调用它的时候,限定名不是对象,而是类名(Txxxxx.Create)。


三、Delphi的析构函数中可以调用纯虚方法

由于在Delphi的析构函数Destroy里,可以调用任何纯虚函数(在C++里这一点是不可想象的),所以可以认为这个时候,虚方法表有一定未被破坏,那么,如果基类就可以决定析构时一定要调用的函数,哪怕这个函数是个虚函数,甚至纯虚函数。


四、Delphi在构造的时候自动将成员变量清零

任何一个Delphi中的类,当它被构造后,它的所有成员变量被清零,布尔型初始为False,字符串初始为空,整型和浮点型初始化为0……而C++没有这样的保证


五、Delphi构造函数中抛出异常会自动先调用析构函数

Delphi里,如果构造函数中抛出了异常,则会自动先执行析构函数,然后再把异常向外抛出;而在C++里,构造函数中若有异常抛出,则析构函数是不会被调用的。


六、Delphi简化了COM接口中的AddRef、Release和QueryInterface

C++里一般用模板对COM接口进行封装,而在Delphi里,AddRef、Release以及QueryInterface都被编译器隐藏掉了,当把一个IUnknown类型的变量(本质上也是一个指针)赋值给另一个变量时,编译器在背后自动AddRef,当一个IUnknown变量离开作用域的时候(再也没有人使用它),Release被自动调用,而QueryInterface被抽象为AS运算符:

procedure Foo(const AParam: IUnknown);
var
  bar: IUnknown;
  other: IStream;
begin
  bar := AParam;  //AParam指向的实例由于赋值操作被AddRef一次
  other := bar as IStream; //调用了一次QueryInterface,引用计数再次加一
end; //返回时,other和bar都离开作用域,分别被调用Release各一次

C++中用模板(比如_com_ptr)也可以使引用计数自动化,不过QueryInterface就没那么方便了。
转自:http://dev.csdn.net/author/seawave/dfe5bb7d242c475f873b9163af019867.html

http://www.cnblogs.com/sideandside/archive/2007/04/26/727863.html

Delphi与C++的语法区别(六点区别) good的更多相关文章

  1. Swift语法之 ---- ?和!区别

    1.常量和变量 Swift语言中是用let来定义常量,并且要初始化.var来定义变量,在let或者var后面申明类型,冒号+空格,然后再加上类型名称. 2.optional(可选)变量 可选变量用于处 ...

  2. count(*)与count(1)、count('xxx')等在使用语法方面的区别

    语法方面: 区别就是:没有区别!!! “*”号是通配符: “*”号是通配符 “*”号是通配符 使用"*"号和使用其他数字和任意非字段字符在使用方面没有任何语法错误; 至于效率方面是 ...

  3. php语法同java语法的基本区别(实例项目需求,php才能熟)

    php语法同java语法的基本区别(实例项目需求,php才能熟) 一.总结 看下面 二.PHP基本语法以及和Java的区别 .表示字符串相加 ->同Java中的. $作为变量的前缀,除此之外,变 ...

  4. [原创] Delphi Create(Application) 和 Create(nil) 的区别

    Delphi Create(Application) 和 Create(nil) 的区别: 例如: Form1:=TForm1.Create(Application); Form1:=TForm1.C ...

  5. Delphi 7以来的Delphi 2009测试版新语法特性

    我晕,Delphi 7 以后增加了这么多有用的语法,我都不知道.真是越学越觉得自己浅薄,自己所作的Delphi项目所用的知识还不够Delphi知识储备体系的十分之一,更别说Delphi还在继续发展. ...

  6. Delphi和C++的语法区别 (关于构造和析构)

    目录 Delphi永远没办法在栈上创建一个对象 Delphi的构造函数更象是个类方法(静态成员函数) Delphi的析构函数中可以调用纯虚方法 Delphi在构造对象时自动将成员变量清零 Delphi ...

  7. [转]【Delphi】 Thread.Queue与Synchronize的区别

    前话:  其实大家要学会看源码, 我接下来要说的这些东东,与其等别人讲,还不如自己搞几个代码试一下,印象还深刻点 TThread.Queue和TThread.Synchronize的区别,效果上:二者 ...

  8. delphi中Record 和Packed Record的区别

    Record 和Packed Record 第一种不带packed关键字的结构体表明编译器编译时要求进行字对齐,而第二种带packed关键字的结构体表明编译器编译该结构体时不需要进行字对齐,这种方式对 ...

  9. Delphi中close与Terminate方法的区别

    在有多个Form窗体时可以体现出来.用close是只关闭本窗体,而用Application.terminate是关闭整个程序,包括所有窗体.(1)当Close是一个主窗体时,程序会退出.Close会发 ...

随机推荐

  1. xmlns:android="http://schemas.android.com/apk/res/android的作用是

    xmlns:android="http://schemas.android.com/apk/res/android的作用是 这个是xml的命名空间,有了他,你就可以alt+/作为提示,提示你 ...

  2. 一个故事讲清楚NIO(转)

    转载请引用:一个故事讲清楚NIO 假设某银行只有10个职员.该银行的业务流程分为以下4个步骤: 1) 顾客填申请表(5分钟): 2) 职员审核(1分钟): 3) 职员叫保安去金库取钱(3分钟): 4) ...

  3. 《C语言深度解剖》面试题整理

    请在40分钟内完成以下20道C语言基础题.在没有任何提示的情况下,如果能得满分,那么你可以扔掉本书了,你的水平已经大大超过了作者:如果能的80分以上,说明你的C语言基础还不错,学习本书可能会比较轻松: ...

  4. C语言数据结构----栈的定义及实现

    本节主要说的是数据结构中的栈的基本定义和实现的方式,其中实现的方式采用的是复用顺序表和单向链表的方式. 一.栈的基本定义 1.栈是一种特殊的线性表,只能从固定的方向进出,而且栈进出的基本原则是:先进栈 ...

  5. C#的事件处理机制

    链接地址:http://blog.csdn.net/niuox/article/details/7527876 在以往的关于事件处理的程序中,我们更多的是采用一种循环等待的方式,即为了检测某个事件是否 ...

  6. FastDFS的学习与使用(大量帖子)

    http://www.oschina.net/p/fastdfs http://bbs.chinaunix.net/forum-240-1.html

  7. perl 访问类方法的几种方式

    [root@wx03 test]# cat Horse.pm package Horse; use base qw(Critter); sub new { my $invocant = shift; ...

  8. 基于visual Studio2013解决面试题之1408桶排序

     题目

  9. Delphi反射

    最近在写一个框架,需要用到反射,与C# java这些原生支持反射的语言不同,delphi对反射的支持相对要弱一些,但也够用了,其实C#的大部分的思想还是从 delphi而来,毕竟都是安德鲁斯的杰作. ...

  10. HBase数据存储格式

    好的数据结构,对于检索数据,插入数据的效率就会很高. 常见的数据结构 B+树 根节点和枝节点非常easy,分别记录每一个叶子节点的最小值,并用一个指针指向叶子节点.  叶子节点里每一个键值都指向真正的 ...