Почему я не могу сделать это в Delphi?Должен ли я получить эту ошибку?[Исключение EAccessViolation] - PullRequest
0 голосов
/ 26 сентября 2019

Я только начал разрабатывать с Delphi.Я просто хотел работать с объектом.Структура, которую я сделал, проста.Есть ли момент, который я пропустил?

  1. Я создал класс в модуле с именем Unit2.

    a.Я создал строковую переменную в этом классе, который я создал (в разделе Public).

  2. Я добавил Unit2 в раздел использований в 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), но фактический вывод '册['.Я даже не знаю, на каком языке мои результаты.

В дополнение ко всему этому, когда я пытаюсь закрыть программу, я получаю ошибку:

Исключение EAccessViolation в модулеProject1exe в 0000848F.Нарушение прав доступа по адресу 0040848F в модуле «Project1.exe».Чтение адреса 3BC03BBC.

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

В Unit1 вы не создаете экземпляр объекта newElement перед записью в его член RektorAdi, поэтому вы уничтожаете случайную память.

В Unit3 вы не создаете экземпляр объекта access перед доступом к его члену RektorAdi, поэтому вы читаете из недопустимой памяти.

Чтобы выполнить то, что вы пытаетесь (установите *Значение 1009 * в одном блоке, а затем доступ к нему в другом блоке), вам необходим одноэлементный объект, который оба блока могут совместно использовать, например:

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 голос
/ 26 сентября 2019
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", где он определен.Переменная «access» в TForm3.Button1Click - это совершенно другая переменная (не потому, что она названа по-другому, а потому, что она определена как переменная LOCAL в совершенно другом методе).Кроме того, эта переменная также не была создана, поэтому она также находится в неопределенном состоянии, что, скорее всего, также приведет к нарушению доступа.

Похоже, вам не хватает базового понимания переменных, областей действияи как передавать значения из одного метода в другой, что выходит за рамки стекового потока для предоставления, но здесь, по крайней мере, это начало того, почему вы получаете нарушение доступа.

0 голосов
/ 26 сентября 2019

Ваш класс 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'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...