zoukankan      html  css  js  c++  java
  • Delphi与C++的语法区别(六点区别) good

    一、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

  • 相关阅读:
    UVa OJ 148 Anagram checker (回文构词检测)
    UVa OJ 134 LoglanA Logical Language (Loglan逻辑语言)
    平面内两条线段的位置关系(相交)判定与交点求解
    UVa OJ 130 Roman Roulette (罗马轮盘赌)
    UVa OJ 135 No Rectangles (没有矩形)
    混合函数继承方式构造函数
    html5基础(第一天)
    js中substr,substring,indexOf,lastIndexOf,split等的用法
    css的textindent属性实现段落第一行缩进
    普通的css普通的描边字
  • 原文地址:https://www.cnblogs.com/findumars/p/5284637.html
Copyright © 2011-2022 走看看