为什么我不能在delphi中做到这一点?我必须得到这个错误吗? [EAccessViolation异常]

时间:2019-09-26 07:46:38

标签: oop delphi

我刚刚开始使用Delphi进行开发。我只是想使用该对象。我制作的结构很简单。我错过了一点吗?

  1. 我在名为Unit2的单元中创建了一个类。

    a。我在我创建的此类中创建了一个字符串变量(在“公共”部分)。

  2. 我在Unit2的“ uses”部分添加了Unit1

    a。我在Unit2中访问了全局变量,并更改了它的值。

  3. 我在创建的Unit2上添加了Unit3

现在,我正在尝试访问从Unit3更改的数据。

unit Unit2;

interface

type
  Gazi = class
  private
    { private declarations }
  public
    RektorAdi : String;
    { public declarations }
  end;

implementation

end.
unit Unit1;

interface

uses
  ..., Unit2, Unit3;

type
  .. (Form Creating)

var
  (Form create)

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  newElement: Gazi;
begin
  newElement.RektorAdi := 'Pala';
  Label1.Caption := 'Successfully';
  Form3.Show;
end;

end.
unit Unit3;

interface

uses
  ... , Unit2;

type
  (Form creating codes)

var
  (Form codes)

implementation

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
var
  access: Gazi;
begin
  Label1.Caption := access.RektorAdi;
end;

end.

我希望得到'Pala'的输出(我对Unit1的更改),但是实际输出是'册['。我什至不知道我的结果是什么语言。

除了所有这些之外,当我尝试关闭程序时,还会收到错误消息:

  

模块Project1exe中的0000848F处异常EAccessViolation。模块'Project1.exe'中地址0040848F的访问冲突。阅读地址3BC03BBC。

3 个答案:

答案 0 :(得分:2)

在Unit1中,您没有在写入newElement对象之前实例化RektorAdi对象,因此浪费了随机内存。

在Unit3中,您没有在访问access对象之前实例化RektorAdi对象,因此您正在从无效的内存中读取数据。

要执行您要尝试的操作(在一个单元中设置RektorAdi值,然后在另一个单元中访问它),则需要两个单元可以共享的单例对象,例如:

unit Unit2;

interface

type
  Gazi = class
  private
    { private declarations }
  public
    RektorAdi : String;
    { public declarations }
  end;

var
  GlobalGazi: Gazi;

implementation

initialization
  GlobalGazi := Gazi.Create;
finalization
  GlobalGazi.Free;

end.
unit Unit1;

interface

uses
  ...;

type
  .. (Form Creating)

var
  (Form create)

implementation

uses
  Unit2, Unit3;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  GlobalGazi.RektorAdi := 'Pala';
  Label1.Caption := 'Successfully';
  Form3.Show;
end;

end.
unit Unit3;

interface

uses
  ...;

type
  (Form creating codes)

var
  (Form codes)

implementation

uses
  Unit2;

{$R *.dfm}

procedure TForm3.Button1Click(Sender: TObject);
begin
  Label1.Caption := GlobalGazi.RektorAdi;
end;

end.

答案 1 :(得分:1)

type
  Gazi = class
         private
           { private declarations }
         public
           { public declarations }
           RektorAdi : String;
        end;

procedure TForm1.Button1Click(Sender: TObject);
var newElement: Gazi;
begin
  newElement.RektorAdi :='Pala';
  Label1.Caption := 'Successfully';
  Form3.Show;
end;

您没有实例化(分配)“ newElement”类所需的空间。所有类都必须通过调用构造函数来创建,该构造函数实例化(分配和初始化)变量以指向正确的类。

您需要执行以下操作:

  newElement := Gazi.Create;
  newElement.RektorAdi :='Pala';

现在,这将确保您在尝试将字符串分配给成员字段RektorAdi时不会出现访问冲突,但这并不能完全解决问题。

newElement是一个LOCAL变量,这意味着它仅在定义它的方法(PROCEDURE)“ TForm1.Button1Click”中可见(并且可以访问)。 TForm3.Button1Click中的变量“ access”是一个完全不同的变量(不是因为名称不同,而是因为在完全不同的方法中将其定义为LOCAL变量)。另外,该变量也没有被实例化,因此它也处于未定义状态,这很可能也会导致那里的访问冲突。

您似乎对变量,范围以及如何将值从一种方法传递给另一种方法缺乏基本的了解,这超出了stackoverflow提供的范围,但这至少是您为什么会遇到访问冲突的开始

答案 2 :(得分:0)

您的班级Gazi应该看起来像这样:

TGazi = class
private
  { private declarations }
  FRektorAdi: String;

  function GetRektorAdi: String; //getter
  procedure SetRektorAdi(value: String); // setter
public
  { public declarations }
  constructor Create;

  property RektorAdi: String read GetRektorAdi write SetRektorAdi;
end;

implementation

constructor TGazi.Create;
begin

end;

function TGazi.GetRektorAdi: String;
begin
    Result := FRektorAdi;
end;

procedure TGazi.SetRektorAdi(value: String);
begin
    if (value <> FRektorAdi) then
        FRektorAdi := value;
end;

end.

然后Unit2可以这样访问其值:

procedure TForm1.Button1Click(Sender: TObject);
var newElement: TGazi;
begin
    try
      newElement := TGazi.Create;
      newElement.RektorAdi := 'Pala';
      ...
      Label1.Caption := newElement.RektorAdi;
    finally
      FreeAndNil(newElement);
    end;
end;

在此事件之外(Button1Click),该类将不再可访问,因为您最终已将其销毁。因此Unit3无法获得实际值'Pala'。