delphi 与 C++的基本语法区别

http://www.cnblogs.com/Braveliu/p/3602784.html


【1】“=”符号

(1)“=”作为比较符。但是,当定义const常量时,“=”又表示赋值符号。而“:=”作为赋值符号。

(2)“=”只表示赋值符号

【2】结构体

(1)record 作为结构体

(2)struct 作为结构体

【3】继承

(1)子类名 = class(父类名)(同时注意这里的“=”也相当于赋值符号)

(2)子类名:public 父类名

【4】class of

(1)A = class of B;  表示A是B的别名。

(2)相当于typedef关键字,定义一个别名。

【5】构造函数

(1)构造函数名为create

(2)构造函数名为类名

【6】析构函数

(1)析构函数名为destroy

(2)析构函数名为类名加~

【7】函数

(1)procedure为过程,function为函数。其区别在于前者没有返回值,后者有返回值。

(2)函数无返回值为void,存在返回值时同function

【8】构造和析构

(1)构造函数必须加constructor,析构函数必须加destructor

(2)不加任何关键字

【9】花括号

(1)begin end代替

(2)花括号{ }作用域

【10】虚函数

(1)virtual写在函数最后面

(2)virtual写在函数最前面

【11】纯虚函数

(1)virtual abstract两个关键字

(2)前面加virtual,后面函数直接“=0”

【12】重载和覆盖

(1)重载overload,override覆盖

(2)参见随笔《重载覆盖重写》

【13】变量声明

(1)变量名在前,类型在后

(2)类型在前,变量名在后

【14】for循环

(1)总是从0到size-1个逐个遍历

(2)for(int i = 0; i < size; ++i){ }

【15】函数返回值

(1)有返回类型的函数,返回变量Result。无返回类型的procedure过程不考虑。

(2)返回值类型与函数的返回类型必须匹配

【16】静态函数

(1)class function 表示静态方法

(2)static关键字

【17】枚举

(1)type  直接枚举名,赋值为枚举成员

(2)enum关键字

【18】不等于

(1)<>表示不等于

(2)!=表示不等于

【19】数组

(1)arrayVar = array[1..24] of Integer;定义一个24个整型大小的数组

(2)int arrayVar[24];注意下标是从0开始。

【20】指针

(1)

type

  PointerToInt = ^Integer; //指向整型的指针

var

  p: ^Integer; //声明一个指向整型的指针变量

  x: Integer;  //声明一个整型变量

p:=@x; // 给指针变量赋值为整数的地址

// change the value in two different ways

x:=10;//改变整型变量的值

p^:=20; // 改变指针指向的地址的数据值

(2)

int* p = NULL;

int a = 100;

p = &a;

a= 200;

*p = 300;

【21】引用

(1)

procedure DoubleTheValue(var Value:Integer)

begin

  value := Value*2;

end;

引用参数用var关键字标识

(2)

void DoubleTheValue(int & nValue)

{   

  nValue = nValue*2;

}

备注:每项的(1)为delphi的表示;(2)为C++表示。



 http://blog.csdn.net/seawave/article/details/1340224

目录

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

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

<span style="font-weight: bold;">procedure</span> Foo;
<span style="font-weight: bold;">var</span>
  obj: TObject; <span style="color: rgb(51, 153, 102);">//这句容易被C++程序员误会。</span>
<span font-weight="" bold="" style="font-weight: bold;">begin</span>
  ...
<span style="font-weight: bold;">end</span>;

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

<span style="color:#0000ff;">void</span> <span style="color:#000000;">Foo</span><span style="color:#000000;">(</span><span style="color:#000000;">)</span> <span style="color:#000000;">{</span>     CObject obj<span style="color:#000000;">;</span> <em><span style="color:#009900;">//</span><span style="color:#009900;">这一句的确在栈上构造了CObject类的</span></em>
    <span style="color:#000000;">.</span><span style="color:#000000;">.</span><span style="color:#000000;">.</span>          <em><span style="color:#009900;">//</span><span style="color:#009900;">一个对象实例,并且将在离开Foo函数时自动析构它</span></em>
<span style="color:#000000;">}</span>

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

<span style="color:#0000ff;">void</span> <span style="color:#000000;">Foo</span><span style="color:#000000;">(</span><span style="color:#000000;">)</span> <span style="color:#000000;">{</span>
    CObject <span style="color:#000000;">*</span> obj<span style="color:#000000;">;</span> <em><span style="color:#009900;">//</span><span style="color:#009900;"> 声明一个CObject类型的指针</span>
                   <span style="color:#009900;">//</span><span style="color:#009900;"> 但没有任何对象被构造或与之关联</span></em>
    <span style="color:#000000;">.</span><span style="color:#000000;">.</span><span style="color:#000000;">.</span>
<span style="color:#000000;">}</span>

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


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

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

<span style="font-weight: bold;">procedure</span> Foo;
<span style="font-weight: bold;">var</span>
  obj: TObject; <span style="color: rgb(0, 128, 128);">//obj本质上只是一个TObject类型的指针</span>
<span font-weight="" bold="" style="font-weight: bold;">begin</span>
  obj := TObject.Create; <span style="color: rgb(0, 128, 128);">//在堆上构造一个TObject对象实例并将其地址赋值给obj</span>
  obj.Free; <span style="color: rgb(0, 128, 128);">//令obj指向的对象析构</span>
<span style="font-weight: bold;">end</span>;

与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运算符:

<span style="font-weight: bold;">procedure</span> Foo(const AParam: IUnknown);
<span style="font-weight: bold;">var</span>
  bar: IUnknown;
  other: IStream;
<span style="font-weight: bold;">begin</span>
  bar := AParam;  <span style="color: rgb(0, 128, 128);">//AParam指向的实例由于赋值操作被AddRef一次</span>
  other := bar as IStream; <span style="color: rgb(51, 153, 102);">//调用了一次QueryInterface,引用计数再次加一</span>
<span style="font-weight: bold;">end</span>; <span style="color: rgb(51, 153, 102);">//返回时,other和bar都离开作用域,分别被调用Release各一次</span>

C++中用模板(比如_com_ptr)也可以使引用计数自动化,不过QueryInterface就没那么方便了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值