如何实现这样效果?
如何实现这样效果?

解决方案 »

  1.   

    首先Delphi中允许把一个类申明为另一个类的友类,很简单,只要两个类在同一个单元中就可以了.......这个是Delphi默认准则.....如果两个类不在一个单元里面,我个人认为无法实现友类的效果.....
      

  2.   

    Delphi没有友元(在同一单元只是类似友元的功能)
    你的方法在Delphi中实现不了( 一家之辞, 我是这样认为的或许哪们高手可以实现)
      

  3.   

    http://richsearch.com/displ.jsp?lid=892583好象有进展了,请看以上网页
      

  4.   

    Delphi存在友类的概念,至于友元我不太清楚它的概念和友类的差别!
      

  5.   

    http://www.delphibbs.com/keylife/images/u40/HowToEnterPrivate.zip
      

  6.   

    TA = class
        private
          a:integer;
        public
          procedure Seta(b:integer);
          function Geta:integer;
        end;
    /////////
    function TA.Geta:integer;
    begin
      result:=a;
    end;procedure TA.Seta(b:integer);
    begin
      a:=b;
      end;
    /////////////////
    var
    c:TA;
    i:PInteger;
    begin
    c:=TA.create;
    c.Seta(1);
    i:= Pinteger(Integer(c) +$04);
    i^:=2;
    SHowmessage(IntTOStr(c.Geta));
    end;
      

  7.   

    1 上面是给你的例子,你可以自己建一个单元测试一下i^:=2;和c.Seta(2);是一样的。注意下面的代码并不是在TA的实例c中.
    2 你将var后的代码封装到另外的类,就实现了你“友类”的目的,但是TA的定义改动后,代码不一定有效
    3 这是直接对对象的内存块进行操作,虽然能够实现,但是非常危险,强烈不推荐!
      

  8.   

    我指的不是你这个意思,我的目的是:
      定义一个类
        TDxf = Class(TObject)
        private
          FDxfObjcet: TDxfObject;
        public
          ReadDxf(FileName: String);
        end;    TDxfObject = Class(TObject)
        private
           X: Integer
           functin Read();
        end;现在TDxf和TDxfObject不在同一个Unit中
    在ReadDxf中要设置 FDxfObject.X的值,而且要调用FDxfObject.Read
      

  9.   

    1 你将var后的代码封装到TDxf类
    procedure TDxf.ReadX():integer;//读取FDxfObjcet.X
    begin
      result:=Pinteger(Integer(FDxfObjcet) +$04)^;
    end;
    FDxfObjcet.Read函数的调用同样可以通过函数指针实现
    2 如果你是想在设计期间使用
    procedure TDxf.ReadX():integer;//读取FDxfObjcet.X
    begin
      result:=FDxfObjcet.X;
    end;
    这样的代码,除非你是在同一个单元!
      

  10.   

    1 你将var后的代码封装到TDxf类
    procedure TDxf.ReadX():integer;//读取FDxfObjcet.X
    begin
      result:=Pinteger(Integer(FDxfObjcet) +$04)^;
    end;
    FDxfObjcet.Read函数的调用同样可以通过函数指针实现
    2 如果你是想在设计期间使用
    procedure TDxf.ReadX():integer;//读取FDxfObjcet.X
    begin
      result:=FDxfObjcet.X;
    end;
    这样的代码,除非你是在同一个单元!
      

  11.   

    To 风焱  这样其实和友类没有任何关系,实际上是绕过Private的限制直接对内存中某个地址进行访问!不过感觉这样到也可行,就是不安全.......
      

  12.   

    To 风焱  这样其实和友类没有任何关系,实际上是绕过Private的限制直接对内存中某个地址进行访问!不过感觉这样到也可行,就是不安全.......
      

  13.   

    首先Delphi中允许把一个类申明为另一个类的友类,很简单,只要两个类在同一个单元中就可以了这个是Delphi默认准则.....
      

  14.   

    firetoucher(风焱) 的思路可以,学习。
      

  15.   

    确实
    直接访问内存怎么能算友元,说到指针我更愿意用c或者win32汇编(笑),在他们中更本没有类的概念吧
    所谓的“友元”,应该不是人为的算法或方法,应该是高级语言提供的一种语言特性。
    同时学过c++与delphi pascal的都应该比较过这两种语言的特性吧
    至少目前为止,在我查阅的国内外资料中,好像没有delphi pascal提供友元特性这一说法
    事实上,友元本身也一定程度破坏了封装性,大概也只有c++想的出来吧
    delphi提供在同一单元的类可以互相任意访问毫无限制已经很开放了,但确实还算不上支持友元
    用指针或取地址,那是完全操作内存的方法,只要语言支持这种数据类型,在任何语言上都能实现你们所谓的“友元”的想法(这是我的想法)。事实上不要说友元了,直接操作内存,连windows api都能改(金山词霸大家没忘?), 这并不能说xx语言提供了修改windows api的特性?(笑)
    如果各位有任何资料说明“delphi pascal”中确实提供支持"友元"特性,请提供强有力证明
    谢谢
      

  16.   

    如果两个类不在一个单元里面,我个人认为delphi无法实现友类的效果.....
      

  17.   

    我支持, Borland 这样设计不知出于什么考虑,  也许他认为友元破坏了对象的封装性,  但在一个单元中又提供了这么一个功能,  也许又考虑了灵活性,  不爽
      

  18.   

    在同一个单无内就可以做到
    DELPHI应该没有友元这个概念
    是C++中过来的但是在一个单元里就可以做到这个效果有些东西讨论多了,没有什么意思
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~我不喜欢友元,它破坏了封装性,不要也罢。
    >>>不能这么说,用时,你就感觉到它的好处
      

  19.   

    可以基本达到“友元”的目的。
    跨单元访问某个类的私有变量,好像很多人都知道直接用指针去取,恐怕都是看了一篇《如何
    跨单元访问私有变量》的文章学的,那种方法不太好,其实最简单的是用一个record模拟在其它单元中声明的类的内存结构,或者最彻底的方法是在本单元做一个模拟类,可以非常方便和
    安全地跨单元访问私有变量。基本上,可以实现跨单元访问私有变量,保护的方法和变量,至于如何访问私有的方法我不大清楚。
    还是多去大富翁的object pascle专区,相比,这里的……,不用我说了。
      

  20.   

    代码如下:
    //类所在的单元
    unit Unit2;interfacetype
      TA = class
      private
        FNum1: string;
        FNum2: Integer;
        FNum3: string;
      public
        constructor Create; virtual;
      end;  TB = class(TA)
      private
        FNote1: string;
        FNote2: Integer;
      public
        constructor Create; override;
      end;
    implementation{ TA }constructor TA.Create;
    begin
      FNum1 := 'FNum1';
      FNum2 := 1;
      FNum3 := 'FNum3';
    end;{ TB }constructor TB.Create;
    begin
      inherited;
      FNote1 := 'FNote1';
      FNote2 := 2;
    end;end.//访问的单元
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TRefRecord = record     //TA
        FNum1: string;
        FNum2: Integer;
        FNum3: string;
      end;
      PRefRecord = ^TRefRecord;  TRefRecord2 = record    //TB
        FNote1: string;
        FNote2: Integer;
      end;
      PRefRecord2 = ^TRefRecord2;  TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses Unit2;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
      pt: PRefRecord;
      a: TA;
    begin
      try
        a := TA.Create;
        pt := Pointer(Integer(a) + TObject.InstanceSize);
        ShowMessage(pt^.FNum3);
      finally
        a.Free;
      end;end;procedure TForm1.Button2Click(Sender: TObject);
    var
      pt2: PRefRecord2;
      b: TB;
    begin
      try
        b := TB.Create;
        pt2 := Pointer(Integer(B) + TA.InstanceSize);
        ShowMessage(pt2.FNote1);
      finally
        B.Free;
      end;end;end.另外一种更简单的方法事模拟类,原理与模拟纪录相同,不再列出。
      

  21.   

    如何访问protected,可以参考Marco Cantu的书,有详细的解释。
    至于如何访问私有方法,不太清楚,我实现不了。
      

  22.   

    Delphi的语言不能支持的
    只能变通解决
      

  23.   

    To Acai  你所说的模拟类的方法才是Delphi中真正的友类概念,但即使是友类也是无法访问私有数据成员的。上面大家提到的那种其实是在破坏友类概念的基础上进行的访问,虽然表面上看是实现了类似友类的概念(甚至突破了友类无法实现私有数据访问的局限),但那毕竟不是Delphi所提倡使用的方法!  至于你列出的利用模拟记录进行跨单元私有数据的访问,我的理解是这样的(我还没有亲手试验过,不过感觉应该可以):申明一个和类的结构类似的记录(这里的结构类似只是真对私有数据的结构而言,可以不考虑方法成员的存在!)就是为了可以让一个记录类型的指针可以指向该类的对象实体。道理很简单,因为堆中对象实体中是不包含任何方法信息的,存在的只有数据信息,所以对于堆中的对象实体,其结构应该是和记录相差不大的(可能只差一个头四个字节的VPTR)。所以这里通过指针释放来访问类的私有数据应该是可以的!
      说白了,这种方法也是绕过了类封装约束进行访问的,不过这种方法的确较那篇文章中提到的方法简单!另外想请教一个细节问题InstanceSize是对象方法,而不是类方法,通过类直接调用以为着什么?
      

  24.   

    Returns the size in bytes of each instance of the object type.Delphi syntax:class function InstanceSize: Longint;C++ syntax:static long __fastcall InstanceSize(TClass cls);long __fastcall InstanceSize(){ return InstanceSize(ClassType()); }DescriptionInstanceSize indicates how many bytes of memory are required for a class’s instance data. InstanceSize is called from methods that allocate and deallocate memory. InstanceSize is not a virtual method, so it cannot be overridden. InstanceSize should be called only when implementing a custom version of NewInstance.InstanceSize是类方法,不是对象方法。
    计算TA时加上TObject.InstanceSize是因为TA的父类是TObject,在堆中每个类都包含它的所有父类,这里是通过计算步长找到TA开始的位置,字段是按照其声明的顺序排列的,所以,通过计算获得TA开始的地址,然后就可以访问了,你可以把TObject.InstanceSize换成4,一样通过,(头4个字节->VMT),至于TB,则加上TA的偏移,同样的道理。我上面说过,可以通过模拟类来实现,让Delphi帮我们计算步长,比模拟纪录更简单。
      

  25.   

    严格说来,Delphi里是不存在“友元”的概念的,上面的方法都是建立在熟悉对象内存结构的基础上实现的,这和“友元”的概念大相径庭,实际上也是一种内存访问技术而已,而且是建立在Delphi这个特定IDE下的,即便如此,就算是通过VMT,一些在其它语言里轻松实现的功能在Delphi里都很难实现或者说很勉强,Delphi里的RTTI确实要比Java\C#这类语言的RTTI\Reflect要逊色的多,李维说Borland还在持续增强Delphi的RTTI中,我倒觉得很难有大的突破了。很多功能不必太刻意了,Delphi的长项不在这里,仅仅是一个优秀个工具罢了,OP离了Delphi这个IDE基本上就一无是处了。
      

  26.   

    应该很简单:
    1、如果两个类在同一单元,就很简单了,相互间可以访问,^_^;
    2、如果不在同一单元,想相互访问也不难:
    假设有两个单元:
    unit unit1;type 
      TClass1 = class(TObject)
        ..
        ..
      end;unit unit2;type 
      TClass2 = class(TObject) 
        ..
        ..
      end;要想在unit2中访问TClass1中的的成员,可以在unit2中新声明一个类
    type
      TClass3 = Class(TClass1);
    这样,通过TClass3就可以访问TClass1了。
      

  27.   

    怎么还不结帖?TClass3差不多就应该是友元了吧?
      

  28.   

    何不再写一个读取私有数据的public方法?
      

  29.   

    >baguli(巴古里): TClass3差不多就应该是友元了吧?不算,unit2中一样访问不到TClass1中的private和protected部分。对于访问private和protected数据成员的方法,估计用模仿类定义有可能是行得通的(有一种例外,没有提供源程序,而只提供了DCU,并且有可能数据成员的位置有可能发生了变化,或者对齐方式不统一)。但是还是没有办法访问非虚的方法(虚拟方法可以到VMT中找,非虚的类似于全局过程/函数,由加载器决定)。
    因此,还是不能算真正友元。
      

  30.   

    应该是不能声明.访问protected部分可以做到.
    但要做到访问private不太可能吧.并且Delphi没有提供这方面的操作.它只支持在同一个Pas文件中友元类.
    在同一个Pas文件中声明的类全是友元类.