2012-02-14 2 views
1

Я создал простой класс, чтобы объяснить мою проблему:Класс не работает, когда определена как глобальная переменная в Дельфах

ttest =class 
private 
    val:boolean; 
published 
    function get:boolean; 
end; 

... 

function ttest.get: boolean; 
begin 
    val:=not val; 
    result:=val; 
end; 

Теперь, если я объявляю локальная переменная ТТЕСТ и вызвать my_var.get; то все работает, но если я объявляю его глобальной переменной, то он больше не сможет получить доступ к полю val, он показывает сообщение об ошибке «Нарушение доступа ...». Я прочитал несколько статей о классах в Delphi, но до сих пор не могу найти свою ошибку.

+5

Вы не создаете экземпляр класса в любом месте, поэтому при вызове 'get' нечего использовать. Я хотел бы предложить, как и где его исправить, но вы не опубликовали какой-либо код, демонстрирующий, что он используется как глобальная переменная (или любой другой вид переменной - вы опубликовали определение класса), поэтому я не могу помогите с этой частью. –

+2

Кен прав, вам нужно создать объекты Delphi. В этом отношении они не похожи на объекты C++. –

+0

Пожалуйста, покажите свой код, где вы создаете экземпляр ttest и вызываете метод get(). –

ответ

5

Вы проигнорировали экземпляр класс.

Глобальные переменные-ссылочные позиции инициализируются до nil, тогда как локальные переменные вообще не инициализируются. Локальная переменная имеет значение, определяемое тем, что оказалось в стеке во время вызова вашей функции, и ваша программа интерпретирует это значение, как если бы это была ссылка TTest, даже если это действительно так. Затем ваша программа считывает значение на этом адресе памяти, чтобы получить значение, которое будет представлять поле val.

Единственная причина, по которой ваш код работает с неглобальной переменной - это удача. Будет ли это удачей или плохим, другое дело. (Удачи, так как ваш код, похоже, работал, и рабочий код всегда хорош. Не повезло, так как вы были бы предупреждены о своей ошибке раньше, если бы ваш код разбился.)

Создайте класс перед использованием ссылок к нему.

x := TTest.Create; 

Теперь вы можете получить доступ поля, методы и свойства объекта с помощью переменной x.

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

+5

«_never игнорировать предупреждение или даже намек.» «Слушайте! Слушайте! –

+0

И я подумал, что я также хотел бы указать, что в любом случае, когда вы вызываете 'Create', вам также нужно вызвать' Free', чтобы уничтожить созданный экземпляр. –

+0

работает при вызове x: = TTest.Create; я попробовал x.create; и это не имело никакого значения, поэтому я решил, что проблема есть где-то еще – Denis

3

В переменных объекта Delphi всегда указываются указатели. Прежде чем вы сможете использовать переменную, вам необходимо инициализировать ее ссылкой на объект. Наиболее распространенный способ сделать это - создать новый объект определенного класса.

procedure Foo; 
var 
    Obj: TObject; 
begin 
    Obj := TObject.Create; 
    try 
    // Do stuff with Obj 
    finally 
    Obj.Free; 
    end; 
end; 

В этом случае Obj запускается как неинициализированный указатель (он указывает на случайную память). Только после того, как мы назначим вновь созданный TObject, Obj является действительной ссылкой на объект.

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

unit myunit; 

interface 

var 
    Obj: TObject; 

implementation 

initialization 

Obj := TObject.Create; 

finalization 

Obj.Free; 

end. 

Переменные, объявленные в разделе интерфейса являются видимыми глобально, переменные, объявленные в секции реализации видны только внутри блока. Следует отметить, что объявление глобальной переменной объекта означает, что любое устройство может перезаписать переменную ссылкой на новый объект, не сначала освободив существующий объект. Это вызовет утечку памяти, так как снова нет автоматической сборки мусора.

0

Класс delphi - это в основном просто описание, а не сам объект.Вы описываете свойства и методы, которые должен иметь конечный объект. И недостающая часть головоломки заключается в том, что вы действительно не сказали Delphi создать объект из своего класса.

Это делается путем вызова конструктора:

mMyInstance:=TTest.Create; 

Конструктор принимает описание класса и создает экземпляр объекта для вас в памяти. Он возвращает указатель на объект, который вы должны хранить в переменной (myInstance в приведенном выше примере) того же типа.

Чтение вашего вопроса, я подозреваю, что вы хотите создать объект «всегда там», немного похожий на объект принтера. Это легко сделать, но точно так же, как и объект принтера - вы должны включить это устройство, прежде чем сможете получить доступ к объекту. Я думаю, что Андерс Э. Андерсен показал, как большинство людей будет инициализировать объект с единичной точки зрения.

Если вы хотите, чтобы объект был доступен с другого устройства, скажем, вашей основной формы или любого другого устройства, сначала добавьте «myunit» в список использования. Затем, чтобы сделать его видимым добавить функцию, например:

function test:ttest; 
Begin 
    result:=obj; 
end; 

И не забудьте добавить «тест функции: Ttest» в интерфейсной части модуля. Затем вы можете использовать объект из другого устройства, как например:

myUnit.test.get; 

Но будьте осторожны! Это довольно старое школьное программирование, и вы рискуете освободить свое подразделение (которое вызывает завершение и тем самым уничтожает ваш объект) до того, как будут выполнены другие блоки. Таким образом, вы рискуете вызвать функцию в объекте, который больше не существует в памяти, что вызывает эффектное нарушение доступа, когда ваша программа закрывается.

Если вы хотите правильно изучить Delphi, перейдите к Delphi Basics и ознакомьтесь с основными принципами. Требуется некоторое время, чтобы выучить новый язык, но вскоре вы получите его.

Удачи вам!

Смежные вопросы