看产生的汇编吗可以看到对于H1.ShowInf是这样的
mov eax,ebx      //ebx为该对象的地址
mov edx,[eax]
call dword ptr [edx]而对于TWorker(H1).ShowInfo
mov eax,ebx
call TWorker.ShowInfo所以就是这样的
可以在TWorker.ShowInfo这样
Writeln('调用TWorker.ShowInfo' + '(' + self.ClassName +')');
就可以看出点意思了

解决方案 »

  1.   

    to xzgyb(老达摩) 
    能说得明白点吗
      

  2.   

    输出的显示表明父类还是父类,ClassName还是TStudent,但是为什么TStrudent还是可以调用到不属于它的方法呢,我主要的迷惑就是在这里.
    这个例子本来写出来是和别人讲解多态的,但是这个结果实在是让我不懂.
      

  3.   

    我想是这样的对于TWorker.ShowInfo是一静态方法,不是c++的那个,前一阵看<<深度探索c++对象模型>>了一点,有一点懂,说的是对于TWoker.ShowInfo这个在内存中就被名子分解为一个独一无二的函数,假如就叫TWOERR_SHOWINFO,函数原型就为TWORKER_SHOWINFO(Self: TWorker)
    当TWorker(H1)时,H1本身就是一个地址,转换为TWorker类型,相当于调用TWORKER_SHOWINFO(TWorker(H1));当然可以调用,当如果TWorker中有一些数据成员的话,并且
    调用ShowInfo访问了这些成员,就会访问到错误的值,因为在此时Self指向的是TStudent空间以上个人理解,说错莫怪
      

  4.   

    关键在于Hi确实是一个对象的应用,但是该对象中本来是没有TWorker的方法,而且如果说通过强制类型转换就可以得到不属于自己的静态编译接口调用,这个不是太荒谬了吗。
    我在java里面测试的话,类似的动作是会有运行时错误的。
      

  5.   

    是有些荒谬,java我不懂,可能java里有运行期类型检测吧
    如果用H1 as TWorker则肯定会出错,
    其实这本身也没有什么荒不荒谬的
    类中的函数本身被名字分裂为一个函数,相当于一静态函数调用
    不要把这些函数想象为占据该类的内存快内,一个对象所占有的内存空间就是
    它所拥有的VPTR和一些数据成员
    无论是对于调用TWoker对象的ShowInfo还是Student对象转为TWorker类型的
    ShowInfo,汇编码都是如此
    mov eax,ebx
    call TWorker.ShowInfoeax即为对象的地址,也即为Self值
    所以ShowInfo输出ClassName时
    对于TWorker(H1)而言为TStudent
    对于真正的TWorker,就为TWorker这是我的理解,继续讨论,呵呵