今天去面试碰到的.

解决方案 »

  1.   

    把这个类实例化 再调用它的private过程
      

  2.   

    把两个窗体类定义到一个pas文件中
      

  3.   

    占个沙发,
    protected里的函数或过程知道怎么调用,Private里的东东,以下代码希望给你一些启发,我相信不能完全帮你解决问题请注意,一定是这种情况,如果其中任何一项位置发生变化,都不可行
    之所以这么说,
    1.这种情况下GetValue及SetValue的入口地址在类信息中是绝对没有保存的,调用指令是 CALL 偏移值
    2.如果节点发生改变,如GetValue函数在protected/published节点中,那么这个函数的地址会保存在类信息中,调用指令会变成 CALL DWORD PTR [REG + Offset] REG=类地址,Offset=vm位置
    这种情况的调用不在本讨论范围,另外讨论,
    TMyClass = TObject
    private
      Function GetValue : integer;
      procedure SetValue(Value : integer);
    public
      Property Value : integer read GetValue write SetValue;
    end;//另一个单元里面这么处理
    procedure TMyClass_Value_ReadWrite;
    begin
      TMyClass(NIL).Value := TMyClass(NIL).Value;
    end;//通过这个函数配合以上过程得到Private节里GetValue函数和SetValue过程的地址
    Function Get_PropertyCallAddress(ReadWriteAdr : Pointer; GetSecondCall : Boolean) : Pointer;
    var
      P : PChar;
      i : integer;
    begin
      Result := NIL;
      P := ReadWriteAdr;
      for i:=0 to 100 do begin
        if P^ = #$E8 then begin
          GetSecondCall := not GetSecondCall;
          if GetSecondCall then begin
            Result := Ptr(integer(P+5) + Pinteger(P+1)^);
            Break;
          end;
        end;
        inc(P);
      end;
    end;//调用TMyClass.GetValue函数
    Function CallTMyClass_GetValue(Obj : TMyClass) : integer;
    var
      PGet : Pointer;
    begin
      PGet := Get_PropertyCallAddress(@TMyClass_Value_ReadWrite , False);
      asm 
        MOV  EAX , Obj;
        CALL P;
        MOV  Result , EAX;
      end;
    end;//调用TMyClass.SetValue函数
    procedure CallTMyClass_GetValue(Obj : TMyClass; NewValue : integer);
    var
      PSet : Pointer;
    begin
      PSet := Get_PropertyCallAddress(@TMyClass_Value_ReadWrite , True);
      asm 
        MOV  EAX , Obj;
        MOV  EDX , NewValue;
        //MOV ECX , 被调函数的第2个参数
        //PUSH 被调函数的第3个参数 and more.
        CALL P;
      end;
    end;
    D7下直接剪的我一个工程里的部分代码,没单独编译测试,希望对你有所启发,
    我目前的知识,有些private里的过程正常情况是不容易得到地址的,这是Delphi编译器的自己的限制,编译时每编译一个函数,会形成一个地址表,在遇到函数调用的代码时查表得到地址,而对Private里的过程,被编译器故意隔离在本单元之外,
    如果给你出这个题的人,是想考验你对编译器的研究有多深的话,那就真的很恶心了
    如果编译器开关里有这么一个开关,允许放开的话,那这就简单了
      

  4.   


    Function Get_PropertyCallAddress(ReadWriteAdr : Pointer; GetSecondCall : Boolean) : Pointer;
    var
      P : PChar;
      i : integer;
    begin
      Result := NIL;
      P := ReadWriteAdr;
      for i:=0 to 100 do begin
        if P^ = #$E8 then begin
          GetSecondCall := not GetSecondCall;
          if GetSecondCall then begin
            Result := Ptr(integer(P+5) + Pinteger(P+1)^);
            Break;
          end;
          inc(P,4);  //漏了这一行
        end;
        inc(P);
      end;
    end;
      

  5.   

    我觉得考官是考你将两个窗口类定义在同一个单元中,通过继承用inherited调用父类的私有过程,楼上说的太难了,应该不会考那么高深的
      

  6.   

    调用protected的倒是可以简单的做到例如要在TForm1中调用TForm2的protected中的一个Test方法可以在TForm1中声明一个类
      TFakeForm = class(TForm2);调用时
        TFakeForm(Form2).Test;这样做是没问题的.但是如果是private的话,我想只能3楼那样,通过偏移量来调用了.具体可以参考一下
    http://www.delphibbs.com/keylife/iblog_show.asp?xid=7198
    跨单元、跨类地访问Delphi类的私有域
      

  7.   

    楼主确定是private而不是protected
      

  8.   

    MethodAddress只能取到published域里的方法地址