现有这样的类型定义及实现:type
  TClass1 = class
  public
    procedure test;virtual;
  end;procedure TClass1.test;
begin
  ShowMessage('1');
end;type
  TClass2 = class(TClass1)
  public
    procedure test;override;
  end;procedure TClass2.test;
begin
  inherited;
  ShowMessage('2');
end;声明变量a为TClass2,如:
var
  a: TClass2;
begin
  ....
  a.test;   <--------------> TClass1(a).test <-----------> (a as TClass1).test 
  //请问上述三总写法的区别。
  //及当a声明为TClass2时,在执行test方法时,如果只执行TClass1中的实现?
end;

解决方案 »

  1.   

    发表一下偶的拙见:a.test :调用的是声明的类的方法,这里应该是TClass2里的test方法
    TClass1(a).test:将类强制转换为TClass1,这里应该调用的是TClass1的方法
    (a as TClass1).test:好象与上面的没区别,待我测试一下看
      

  2.   

    你的第二种写法是C语言中的
    第三种写法是DELPHI中的
    如果你这样写的话,它们是一点区别也没有的!
    你可以写第三句前在一句if (a is TClass1) then
    这样就安全的多了!
      

  3.   

    //请问上述三总写法的区别。
    ----------------
      没有区别,他是通过虚函数表查找执行的函数的,
    无论你怎么转型他还是执行同一个函数。//及当a声明为TClass2时,在执行test方法时,如果只执行TClass1中的实现?
    -------------------------------------------------------------------
    var
      a: TClass2;
    begin
      a := TClass2(TClass1.Create());  //-
      TClass1(a).test();
    end;  个人认为不提倡这种用法,
    向下类型转换是不安全的。
      

  4.   

    谢谢dragon191(幻世星龙) 参与:)//你可以写第三句前在一句if (a is TClass1) then,这样就安全的多了!
    这样是好的做法:)
    晕了,,,>>>向下类型转换是不安全的。
    倒底是向下还是向上?我刚才一直在说向上:)
      

  5.   

    倒底是向下还是向上?我刚才一直在说向上:)看请我写的:
     a := TClass2(TClass1.Create());  //-
    只有这样创建才可能在执行test方法时,执行TClass1中的实现;
      

  6.   

    向上是安全的。a = class (b)oa: a;
    ob: b;b := (oa as b); // ok改變了尋址空間 由較大的地址范圍->較小地 而且還是繼承關系 子類是有一份復類地data地 所以 是安全地 而反過來則不一定了。
      

  7.   

    to meiqingsong(阿飛):
    如果像你那样用TClass1.Create的话
    那跟声明
    aa: TClass1没什么区别了虽然在创建后强制转换到了TClass2,但我想,执行任何TClass2中实现的方法都会抱错(直觉认为)
      

  8.   

    >>>就虚函数而言
    abstract函数呢?
      

  9.   

    是啊,就是虚函数啊,CLASS2只是继承CLASS1,而且实现了CLASS1没实现的功能,跟其他语言的抽象类实现没什么区别的
      

  10.   

    >>>就虚函数而言
    abstract函数呢?
    abstract 必須是 virtual or dynamic method..抽象的 表示不用在本處顯示,只是聲明一個接口而已,達到接口的目的..
      

  11.   

    //及当a声明为TClass2时,在执行test方法时,如果只执行TClass1中的实现?
    -------------------------------------------------------------------
    var
      a: TClass2;
    begin
      a := TClass2(TClass1.Create());  //-
      TClass1(a).test();
    end;  个人认为不提倡这种用法,
    向下类型转换是不安全的。
    ======================================================================这样确实不安全
    但是这样应该没啥问题var
      a: TClass2;
    begin
      a:=TClass2.Create;
      Tclass1(integer(a.ClassParent)-76).test;
      a.free; 
    end;
      

  12.   

    //请问上述三总写法的区别。a.test没啥好说的说说 TClass1(a)和(a as TClass1)    前者属于变量的类型转换,可以转换任何变量到任何类型,倘若它们具有相同的尺寸并且不要混淆整数和实数,就可以了。    后者属于as运算符,用法表达式: object as class
        在运行时,object必需是class表示的类或其后裔类的实例,或者是nil;否则引发异常。如果object的声明类型与class无关,即它们二者各自独立并且其中任意一个不是另一个的祖先,那么将导致编译错误。
      

  13.   

    呵呵,头晕的东西http://lysoft.7u7.net
      

  14.   

    a是个对象,说到底其实是一个指针,是那个类创建的它,他的test就指向那个类的test函数入口地址;所以楼主给的例子中,虽然改变了指针的类型,但是指针的地址还是没有改变的,所以调用之后的执行结果是一样的,
    至于abstract函数是纯虚函数,正如beyondtkl(大龙驹<學,無涯>) 所说,只是提供一个函数接口,为的就是达到函数借口复用的目的,所有的实现都是在子类当中完成的。
    例如:在Tparent中定义了一个纯虚函数test,Tchild1和Tchild2都是他的子类,非别有实现,那么创建两个子类的对象child1和child2,TParent(child1).test和TParent(Child2).test的调用结果是不一样的。但是都可以用.test这个函数名字来调用,例如函数的参数是TParent的时候,就会给函数的调用带来很大的便利,这就是所谓的函数借口复用...
      

  15.   

    a是个对象,说到底其实是一个指针,是那个类创建的它,他的test就指向那个类的test函数入口地址;所以楼主给的例子中,虽然改变了指针的类型,但是指针的地址还是没有改变的,所以调用之后的执行结果是一样的,
    至于abstract函数是纯虚函数,正如beyondtkl(大龙驹<學,無涯>) 所说,只是提供一个函数接口,为的就是达到函数借口复用的目的,所有的实现都是在子类当中完成的。
    例如:在Tparent中定义了一个纯虚函数test,Tchild1和Tchild2都是他的子类,非别有实现,那么创建两个子类的对象child1和child2,TParent(child1).test和TParent(Child2).test的调用结果是不一样的。但是都可以用.test这个函数名字来调用,例如函数的参数是TParent的时候,就会给函数的调用带来很大的便利,这就是所谓的函数借口复用...
      

  16.   

    谢谢这么多人的参与:)to AD:var
      a: TClass2;
    begin
      a:=TClass2.Create;
      Tclass1(integer(a.ClassParent)-76).test; // <--------- 为什么是-76呀??这句给解释一下:)
      a.free; 
    end;
      

  17.   

    楼上说的不错以前有篇很火的帖子记得叫跨父类继承的当时俺看的眼冒金星最后楼主总结了几种方法,都挺有代表性的CoolSlob可以搜搜看
      

  18.   

    AD最好了:)帮偶搜到了paste过来吧:p
      

  19.   

    76..是相對的offset呀。。system.pas有寫的。
      

  20.   

    学习!顶!
    刘艺的《Delphi面向对象编程思想》一书中好像有详细讲述,可惜我手头上没这本书!
      

  21.   

    >>>刘艺的《Delphi面向对象编程思想》一书中好像有详细讲述,可惜我手头上没这本书!
    这本书我倒是有,现在没心情重看了:)
      

  22.   

    好问题,学习BTW:楼主的主页现在搬哪去了
      

  23.   

    >>BTW:楼主的主页现在搬哪去了
    放口袋里了:)主页又没什么东西,没开了。 piantang(菠菜汤)好熟悉的名字。