如何正确传递带有 var 前缀的对象类型的参数?

发布于 2024-10-20 11:03:16 字数 7847 浏览 6 评论 0原文

总结:

type 
  MyObject = object
  end;

  MyRecord = record
  end;

  MyClass = class
  end;

  procedure ProcA(aMyObject: MyObject);
  procedure ProcB(var aMyObject: MyObject);
  procedure ProcC(aMyRecord: MyRecord);
  procedure ProcD(var aMyRecord: MyRecord);
  procedure ProcE(aMyClass: MyOClass);
  procedure ProcF(var aMyClass: MyClass);
  1. MyObjectMyRecord 是值类型,而 MyClass 是引用类型。
  2. 值类型变量的赋值会复制该变量;引用类型变量的赋值将复制引用。
  3. ProcAProcC 中的参数是原始参数的副本。
  4. ProcBProcD 中的参数是原始参数。
  5. ProcE 中的参数是原始引用的副本。
  6. ProcF 中的参数是原始引用。
  7. 关于如何包装在agg_2D.pas单元中声明的Agg2D对象来绘制,请参见下面David的回答。

=============================================
我正在学习使用 AggPas,它是一个纯 Pascal 矢量图形绘图 API。具体来说,使用包含 Agg2D 对象的单元 agg_2D.pas,而不是包含 TAgg2D 类的单元 Agg2D.pas。选择单元 agg_2D.pas 而不是单元 Agg2D.pas 的原因是为了跨平台能力。

但是,我无法正确传递带有 var 前缀的 Agg2D 对象类型的参数。如下面的代码所示,我想将 TForm1 创建的 Agg2D 对象传递给另一个实际负责绘制形状的类。然而,它不起作用。您能帮忙评论一下可能的原因吗?看来我一定错过了有关对象类型的重要概念。任何建议表示赞赏!您可以新建一个VCL应用程序,附加FormCreate处理程序,并逐行注释掉绘图代码以查看效果。

    unit Unit1;

    interface

    uses
      agg_2D,
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TRenderEngine_BMP = class;
      TRenderEngine_Agg = class;
      TForm1 = class;

      TRenderEngine_BMP = class
      private
        fBMP: TBitmap;
      public
        constructor Create(var aBMP: TBitmap);
        procedure DrawEllipse;
      end;

      TRenderEngine_Agg = class
      private
        fVG: Agg2D;
      public
        constructor Create(var aVG: Agg2D);
        procedure DrawEllipse;
      end;

      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }

        fBMP: TBitmap;
        fVG: Agg2D;
        fEngine_BMP: TRenderEngine_BMP;
        fEngine_Agg: TRenderEngine_Agg;

        procedure AttachBMP(var aVG: Agg2D; var aBMP: TBitmap);
        procedure OnSceneResize(Sender: TObject);
        procedure OnScenePaint(Sender: TObject);
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    uses
      Math;

    { TRenderEngine_BMP }

    constructor TRenderEngine_BMP.Create(var aBMP: TBitmap);
    begin
      Self.fBMP := aBMP;
    end;

    procedure TRenderEngine_BMP.DrawEllipse;
    begin
      Self.fBMP.Canvas.ellipse(20, 20, 80, 80);
    end;

    { TRenderEngine_Agg }

    constructor TRenderEngine_Agg.Create(var aVG: Agg2D);
    begin
      Self.fVG := aVG;
    end;

    procedure TRenderEngine_Agg.DrawEllipse;
    begin
      Self.fVG.ellipse(50, 50, 30, 30);
    end;

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Self.OnResize := {$IFDEF FPC} @ {$ENDIF} OnSceneResize;
      Self.OnPaint := {$IFDEF FPC} @ {$ENDIF} OnScenePaint;

      fBMP := TBitmap.Create;
      fBMP.PixelFormat := pf32bit;
      fBMP.Canvas.Brush.Style := bsSolid;
      fBMP.Canvas.Brush.Color := clBlue;
      fBMP.Width := ClientWidth;
      fBMP.Height := ClientHeight;

      fVG.Construct;
      Self.AttachBMP(fVG, fBMP);

      fEngine_BMP := TRenderEngine_BMP.Create(fBMP);
      fEngine_Agg := TRenderEngine_Agg.Create(fVG);
    end;

    procedure TForm1.AttachBMP(var aVG: Agg2D; var aBMP: TBitmap);
    var
      tmpBuffer: pointer;
      tmpStride: integer;
    begin
      tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);

      if tmpStride < 0 then
        tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
      else
        tmpBuffer := aBMP.ScanLine[0];

      aVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
    end;

    procedure TForm1.OnScenePaint(Sender: TObject);
    begin
      Self.fBMP.Canvas.FillRect(Self.ClientRect);

    //  Self.fBMP.Canvas.ellipse(20, 20, 80, 80);  // Work
    //  Self.fVG.ellipse(50, 50, 30, 30);          // Work
    //  Self.fEngine_BMP.DrawEllipse;              // Work
      Self.fEngine_Agg.DrawEllipse;                // Do not work

      Self.Canvas.Draw(0, 0, fBMP);
    end;

    procedure TForm1.OnSceneResize(Sender: TObject);
    begin
      fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
      fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);

      Self.AttachBMP(fVG, fBMP);
    end;

    end.

如果我删除过程参数中所有出现的 var 前缀,第二个画圆代码也会停止工作,我不太明白。为方便起见,单位如下所示:

    unit Unit1;

    interface

    uses
      agg_2D,
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TRenderEngine_BMP = class;
      TRenderEngine_Agg = class;
      TForm1 = class;

      TRenderEngine_BMP = class
      private
        fBMP: TBitmap;
      public
        constructor Create(aBMP: TBitmap);
        procedure DrawEllipse;
      end;

      TRenderEngine_Agg = class
      private
        fVG: Agg2D;
      public
        constructor Create(aVG: Agg2D);
        procedure DrawEllipse;
      end;

      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }

        fBMP: TBitmap;
        fVG: Agg2D;
        fEngine_BMP: TRenderEngine_BMP;
        fEngine_Agg: TRenderEngine_Agg;

        procedure AttachBMP(aVG: Agg2D; aBMP: TBitmap);
        procedure OnSceneResize(Sender: TObject);
        procedure OnScenePaint(Sender: TObject);
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    uses
      Math;

    { TRenderEngine_BMP }

    constructor TRenderEngine_BMP.Create(aBMP: TBitmap);
    begin
      Self.fBMP := aBMP;
    end;

    procedure TRenderEngine_BMP.DrawEllipse;
    begin
      Self.fBMP.Canvas.ellipse(20, 20, 80, 80);
    end;

    { TRenderEngine_Agg }

    constructor TRenderEngine_Agg.Create(aVG: Agg2D);
    begin
      Self.fVG := aVG;
    end;

    procedure TRenderEngine_Agg.DrawEllipse;
    begin
      Self.fVG.ellipse(50, 50, 30, 30);
    end;

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Self.OnResize := {$IFDEF FPC} @ {$ENDIF} OnSceneResize;
      Self.OnPaint := {$IFDEF FPC} @ {$ENDIF} OnScenePaint;

      fBMP := TBitmap.Create;
      fBMP.PixelFormat := pf32bit;
      fBMP.Canvas.Brush.Style := bsSolid;
      fBMP.Canvas.Brush.Color := clBlue;
      fBMP.Width := ClientWidth;
      fBMP.Height := ClientHeight;

      fVG.Construct;
      Self.AttachBMP(fVG, fBMP);

      fEngine_BMP := TRenderEngine_BMP.Create(fBMP);
      fEngine_Agg := TRenderEngine_Agg.Create(fVG);
    end;

    procedure TForm1.AttachBMP(aVG: Agg2D; aBMP: TBitmap);
    var
      tmpBuffer: pointer;
      tmpStride: integer;
    begin
      tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);

      if tmpStride < 0 then
        tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
      else
        tmpBuffer := aBMP.ScanLine[0];

      aVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
    end;

    procedure TForm1.OnScenePaint(Sender: TObject);
    begin
      Self.fBMP.Canvas.FillRect(Self.ClientRect);

    //  Self.fBMP.Canvas.ellipse(20, 20, 80, 80);  // Work
    //  Self.fVG.ellipse(50, 50, 30, 30);          // Do not Work
    //  Self.fEngine_BMP.DrawEllipse;              // Work
      Self.fEngine_Agg.DrawEllipse;                // Do not work

      Self.Canvas.Draw(0, 0, fBMP);
    end;

    procedure TForm1.OnSceneResize(Sender: TObject);
    begin
      fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
      fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);

      Self.AttachBMP(fVG, fBMP);
    end;

    end.

Summarization:

type 
  MyObject = object
  end;

  MyRecord = record
  end;

  MyClass = class
  end;

  procedure ProcA(aMyObject: MyObject);
  procedure ProcB(var aMyObject: MyObject);
  procedure ProcC(aMyRecord: MyRecord);
  procedure ProcD(var aMyRecord: MyRecord);
  procedure ProcE(aMyClass: MyOClass);
  procedure ProcF(var aMyClass: MyClass);
  1. MyObject and MyRecord are value type, whereas MyClass is reference type.
  2. Assignment of variable of value type will copy the variable; assignment of variable of reference type will copy the reference.
  3. The arguments in ProcA and ProcC are copies of the original ones.
  4. The arguments in ProcB and ProcD are the original ones.
  5. The argument in ProcE is a copy of the original reference.
  6. The argument in ProcF is the original reference.
  7. Regarding how to wrap up Agg2D object, which is declared in the unit agg_2D.pas, to draw, please see David's answer below.

===========================================
I am learning to use the AggPas which is a pure-pascal vector graphics drawing API. Specifically the unit agg_2D.pas, which contains Agg2D object, is used instead of the unit Agg2D.pas, which contains TAgg2D class. The reason of choosing the unit agg_2D.pas over the unit Agg2D.pas is for cross-platform ability.

However, I cannot correctly pass through argument of Agg2D object type with var prefix. As shown in the following code, I want to pass the Agg2D object created by TForm1 to another class that is actual responsible to draw shapes. However, it does not work. Could you help to comment on the possible reason? It seems I must have missed important concepts regarding object type. Any suggestion is appreciated! You could new a VCL application, attach the FormCreate handler, and comment out the drawing codes line by line to see the effect.

    unit Unit1;

    interface

    uses
      agg_2D,
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TRenderEngine_BMP = class;
      TRenderEngine_Agg = class;
      TForm1 = class;

      TRenderEngine_BMP = class
      private
        fBMP: TBitmap;
      public
        constructor Create(var aBMP: TBitmap);
        procedure DrawEllipse;
      end;

      TRenderEngine_Agg = class
      private
        fVG: Agg2D;
      public
        constructor Create(var aVG: Agg2D);
        procedure DrawEllipse;
      end;

      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }

        fBMP: TBitmap;
        fVG: Agg2D;
        fEngine_BMP: TRenderEngine_BMP;
        fEngine_Agg: TRenderEngine_Agg;

        procedure AttachBMP(var aVG: Agg2D; var aBMP: TBitmap);
        procedure OnSceneResize(Sender: TObject);
        procedure OnScenePaint(Sender: TObject);
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    uses
      Math;

    { TRenderEngine_BMP }

    constructor TRenderEngine_BMP.Create(var aBMP: TBitmap);
    begin
      Self.fBMP := aBMP;
    end;

    procedure TRenderEngine_BMP.DrawEllipse;
    begin
      Self.fBMP.Canvas.ellipse(20, 20, 80, 80);
    end;

    { TRenderEngine_Agg }

    constructor TRenderEngine_Agg.Create(var aVG: Agg2D);
    begin
      Self.fVG := aVG;
    end;

    procedure TRenderEngine_Agg.DrawEllipse;
    begin
      Self.fVG.ellipse(50, 50, 30, 30);
    end;

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Self.OnResize := {$IFDEF FPC} @ {$ENDIF} OnSceneResize;
      Self.OnPaint := {$IFDEF FPC} @ {$ENDIF} OnScenePaint;

      fBMP := TBitmap.Create;
      fBMP.PixelFormat := pf32bit;
      fBMP.Canvas.Brush.Style := bsSolid;
      fBMP.Canvas.Brush.Color := clBlue;
      fBMP.Width := ClientWidth;
      fBMP.Height := ClientHeight;

      fVG.Construct;
      Self.AttachBMP(fVG, fBMP);

      fEngine_BMP := TRenderEngine_BMP.Create(fBMP);
      fEngine_Agg := TRenderEngine_Agg.Create(fVG);
    end;

    procedure TForm1.AttachBMP(var aVG: Agg2D; var aBMP: TBitmap);
    var
      tmpBuffer: pointer;
      tmpStride: integer;
    begin
      tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);

      if tmpStride < 0 then
        tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
      else
        tmpBuffer := aBMP.ScanLine[0];

      aVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
    end;

    procedure TForm1.OnScenePaint(Sender: TObject);
    begin
      Self.fBMP.Canvas.FillRect(Self.ClientRect);

    //  Self.fBMP.Canvas.ellipse(20, 20, 80, 80);  // Work
    //  Self.fVG.ellipse(50, 50, 30, 30);          // Work
    //  Self.fEngine_BMP.DrawEllipse;              // Work
      Self.fEngine_Agg.DrawEllipse;                // Do not work

      Self.Canvas.Draw(0, 0, fBMP);
    end;

    procedure TForm1.OnSceneResize(Sender: TObject);
    begin
      fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
      fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);

      Self.AttachBMP(fVG, fBMP);
    end;

    end.

If I delete all occurrences of the var prefix of procedure arguments, the second circle-drawing code also stops working, which I don't quite understand. The unit is shown as below for your convenience:

    unit Unit1;

    interface

    uses
      agg_2D,
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TRenderEngine_BMP = class;
      TRenderEngine_Agg = class;
      TForm1 = class;

      TRenderEngine_BMP = class
      private
        fBMP: TBitmap;
      public
        constructor Create(aBMP: TBitmap);
        procedure DrawEllipse;
      end;

      TRenderEngine_Agg = class
      private
        fVG: Agg2D;
      public
        constructor Create(aVG: Agg2D);
        procedure DrawEllipse;
      end;

      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }

        fBMP: TBitmap;
        fVG: Agg2D;
        fEngine_BMP: TRenderEngine_BMP;
        fEngine_Agg: TRenderEngine_Agg;

        procedure AttachBMP(aVG: Agg2D; aBMP: TBitmap);
        procedure OnSceneResize(Sender: TObject);
        procedure OnScenePaint(Sender: TObject);
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    uses
      Math;

    { TRenderEngine_BMP }

    constructor TRenderEngine_BMP.Create(aBMP: TBitmap);
    begin
      Self.fBMP := aBMP;
    end;

    procedure TRenderEngine_BMP.DrawEllipse;
    begin
      Self.fBMP.Canvas.ellipse(20, 20, 80, 80);
    end;

    { TRenderEngine_Agg }

    constructor TRenderEngine_Agg.Create(aVG: Agg2D);
    begin
      Self.fVG := aVG;
    end;

    procedure TRenderEngine_Agg.DrawEllipse;
    begin
      Self.fVG.ellipse(50, 50, 30, 30);
    end;

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Self.OnResize := {$IFDEF FPC} @ {$ENDIF} OnSceneResize;
      Self.OnPaint := {$IFDEF FPC} @ {$ENDIF} OnScenePaint;

      fBMP := TBitmap.Create;
      fBMP.PixelFormat := pf32bit;
      fBMP.Canvas.Brush.Style := bsSolid;
      fBMP.Canvas.Brush.Color := clBlue;
      fBMP.Width := ClientWidth;
      fBMP.Height := ClientHeight;

      fVG.Construct;
      Self.AttachBMP(fVG, fBMP);

      fEngine_BMP := TRenderEngine_BMP.Create(fBMP);
      fEngine_Agg := TRenderEngine_Agg.Create(fVG);
    end;

    procedure TForm1.AttachBMP(aVG: Agg2D; aBMP: TBitmap);
    var
      tmpBuffer: pointer;
      tmpStride: integer;
    begin
      tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);

      if tmpStride < 0 then
        tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
      else
        tmpBuffer := aBMP.ScanLine[0];

      aVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
    end;

    procedure TForm1.OnScenePaint(Sender: TObject);
    begin
      Self.fBMP.Canvas.FillRect(Self.ClientRect);

    //  Self.fBMP.Canvas.ellipse(20, 20, 80, 80);  // Work
    //  Self.fVG.ellipse(50, 50, 30, 30);          // Do not Work
    //  Self.fEngine_BMP.DrawEllipse;              // Work
      Self.fEngine_Agg.DrawEllipse;                // Do not work

      Self.Canvas.Draw(0, 0, fBMP);
    end;

    procedure TForm1.OnSceneResize(Sender: TObject);
    begin
      fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
      fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);

      Self.AttachBMP(fVG, fBMP);
    end;

    end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如此安好 2024-10-27 11:03:16

我很难理解你在这里做什么。我认为您的基本问题是 Agg2D 是一个 object ,因此也是一个值类型。你拿一份它的副本,这样就有两份而不是一份。作者选择使用 object 而不是类,但这样做需要您对 TObject 后代的值语义而不是引用语义非常警惕。

让它工作的快速技巧是将 fVG: Agg2D; 更改为 fVG: ^Agg2D; 并在 TRenderEngine_Agg.Create 中更改 >Self.fVG := aVGSelf.fVG := @aVG。通过这种改变,椭圆就被绘制出来了。

现在,我认为你需要重新考虑你的设计。如果您想将 Agg2D 对象包装在渲染类中,那就没问题,但您不能复制 Agg2D 对象。

以下是我将如何编写代码来处理该问题:

TRenderEngine_Agg = class
private
  fVG: Agg2D;
public
  constructor Create;
  procedure AttachBMP(aBMP: TBitmap);
  procedure DrawEllipse;
end;

constructor TRenderEngine_Agg.Create;
begin
  fVG.Construct;
end;

procedure TRenderEngine_Agg.AttachBMP(aBMP: TBitmap);
var
  tmpBuffer: pointer;
  tmpStride: integer;
begin
  tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);

  if tmpStride < 0 then
    tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
  else
    tmpBuffer := aBMP.ScanLine[0];

  fVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
end;

procedure TRenderEngine_Agg.DrawEllipse;
begin
  Self.fVG.fillColor(30, 50, 20);
  Self.fVG.blendMode(BlendContrast );
  Self.fVG.ellipse(50, 50, 30, 30);
end;

procedure TForm20.OnSceneResize(Sender: TObject);
begin
  fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
  fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);

  fEngine_Agg.AttachBMP(fBMP);
end;

这个想法是将所有与 Agg2D 对象有关的内容放在 TRenderEngine_Agg 中。如果你做到这一点,那么我想你会成为金子!

I'm struggling to understand what you are doing here. I think your basic problem is that Agg2D is an object and so is a value type. You take a copy of it so that there are two copies rather than one. The author has elected to use object rather than a class but doing so requires you to be very alert to the value semantics rather than reference semantics of TObject descendants.

The quick hack to get this to work is to change fVG: Agg2D; to fVG: ^Agg2D; and in TRenderEngine_Agg.Create change Self.fVG := aVG to Self.fVG := @aVG. With that change the ellipse is drawn.

Now, I think you need to re-consider your design. If you want to wrap up an Agg2D object in a rendering class, then that would be fine, but you must not take copies of the Agg2D object.

Here's how I would write your code to deal with the problem:

TRenderEngine_Agg = class
private
  fVG: Agg2D;
public
  constructor Create;
  procedure AttachBMP(aBMP: TBitmap);
  procedure DrawEllipse;
end;

constructor TRenderEngine_Agg.Create;
begin
  fVG.Construct;
end;

procedure TRenderEngine_Agg.AttachBMP(aBMP: TBitmap);
var
  tmpBuffer: pointer;
  tmpStride: integer;
begin
  tmpStride := integer(aBMP.ScanLine[1]) - integer(aBMP.ScanLine[0]);

  if tmpStride < 0 then
    tmpBuffer := aBMP.ScanLine[aBMP.Height - 1]
  else
    tmpBuffer := aBMP.ScanLine[0];

  fVG.attach(tmpBuffer, aBMP.Width, aBMP.Height, tmpStride);
end;

procedure TRenderEngine_Agg.DrawEllipse;
begin
  Self.fVG.fillColor(30, 50, 20);
  Self.fVG.blendMode(BlendContrast );
  Self.fVG.ellipse(50, 50, 30, 30);
end;

procedure TForm20.OnSceneResize(Sender: TObject);
begin
  fBMP.Width := IfThen(ClientWidth > 0, ClientWidth, 2);
  fBMP.Height := IfThen(ClientHeight > 0, ClientHeight, 2);

  fEngine_Agg.AttachBMP(fBMP);
end;

The idea is to put everything to do with the Agg2D object inside TRenderEngine_Agg. If you do this then I think you'll be golden!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文