Недавно я увидел в Интернете, как один пользователь сети спросил: Как определить, доступен ли указатель объекта? Другими словами, как определить, указывает ли указатель объекта на реальный экземпляр объекта, который можно использовать? На самом деле это не должно быть проблемой. Потому что программист должен иметь возможность контролировать свою программу, чтобы не получить доступ к недопустимому указателю, потому что создание и уничтожение всех экземпляров объекта находится под его контролем. И даже если нет прямого способа определить, доступен ли указатель объекта, это можно сделать и другими косвенными способами (например, с помощью некоторых идентификаторов и т. д.) (например, когда мы уничтожаем экземпляр объекта, мы устанавливаем указатель на указатель объекта равен нулю). Но если отбросить два упомянутых выше пункта и просто изучить, существует ли способ определить, доступен ли указатель объекта в Delphi, что произойдет?
В Object Pascal класс может иметь два типа методов: один называется методом объекта (метод объекта), а другой — методом класса (метод класса). Так называемый метод объекта означает, что определение метода предназначено для объекта (или экземпляра), поэтому вызов метода должен быть основан на объекте (или экземпляре). Например, деструктор Destroy класса является объектом. метод (на самом деле, мы часто используем большинство методов объекта). Метод класса относится к определению метода, основанному на классе объектов, поэтому вызов метода не обязательно должен быть основан на конкретном экземпляре объекта, например, на конструкторе Create класса. Это дает нам некоторое вдохновение. Определение доступности указателя объекта, по-видимому, выполняется с помощью следующих шагов. Во-первых, мы можем определить, равен ли указатель объекта нулю. Если да, то все готово, а если нет, то попробуйте выполнить объектный метод объекта, чтобы увидеть, есть ли исключения, такие как недопустимый доступ к памяти. Это используется для определения доступности объекта. Используйте следующий код, чтобы проверить нашу идею:
вар
Объект: ТОбъект;
начинать
Obj := TObject.Create //1.
Obj.Free; //2. Освободите только что созданный объект, при этом память будет перезагружена;
Если Obj = nil, то //3 Определим, пуст ли указатель (этот шаг часто оказывается неудачным, поскольку объект
// выпущен, Delphi не будет автоматически очищать указатель объекта)
ShowMessage('Указатель объекта недоступен.')
еще
начинать
Пытаться
Если Obj.ClassType = TObject, то //4. Вызов метода объекта TObject.
ShowMessage('Тип объекта — TObject');
Кроме
ShowMessage('Указатель объекта недоступен.')
Конец;
конец;
конец;
Выполняя приведенный выше код, мы обнаруживаем, что Obj.ClassType все еще доступен, даже если Obj.Free был выполнен. Это показывает, что не все методы объекта должны зависеть от экземпляра объекта, чтобы быть доступными. Причина в том, что этому методу объекта не требуется доступ к памяти, запрошенной экземпляром объекта. В этом смысле метод TObject.ClassType не похож на метод реального объекта, а скорее напоминает метод класса.
Выполняя приведенный выше код, мы также можем обнаружить, что когда объект выполняет метод Free, он освобождает только всю память, к которой он обращался при создании, но это не влияет на значение самого указателя объекта. Указатель объекта по-прежнему указывает на исходный адрес памяти. При этом из-за особенностей реализации некоторых методов объекта (например, ClassType), даже если объект был освобожден, результат вызова метода объекта все равно корректен.
Подводя итог, можно сделать вывод, что то, можно ли считать указатель объекта доступным, зависит от того, предоставляет ли класс, к которому принадлежит указатель объекта, способ доступа к памяти экземпляра объекта — этот способ также может быть Методы также могут быть быть свойствами. Итак, какова сейчас ситуация конкретно по каждой категории?
TObject, этот класс является предком всех классов, судить невозможно.
TPersistent, производный от TObject, не требует дополнительной памяти при создании экземпляра объекта, поэтому судить невозможно.
TComponent, производный от TPersistent, добавляет множество свойств, которые требуют использования дополнительной памяти при создании экземпляра объекта, поэтому теоретически это оценивается. Код выглядит следующим образом:
функция ComponentExists(AComponent: TComponent): Boolean;
начинать
пытаться
AComponent.Hasparent; //Примечание: это предложение также может быть «AComponent.Tag;»
//Или "AComponent.Name"
результат := Истина;
кроме
результат := Ложь;
конец;
конец;
Вызвав ComponentExists, мы можем узнать, доступен ли указатель объекта типа TComponent, независимо от того, был ли указатель объекта освобожден или установлен в ноль.
Для других классов, таких как TControl, TWinControl или TButton и т. д., если они являются производными от TComponent, метод оценки TComponent по-прежнему применяется.
Существуют и другие пользовательские классы. Если они напрямую получены из классов, которые не могут быть оценены (например, TObject и TPersistent), но нет атрибутов, требующих использования памяти во время создания экземпляра, то иначе судить невозможно; возможно. Согласно примеру:
Предположим, у нас есть класс TPerson, определенный следующим образом:
TPerson = Класс(TObject)
Частный
FSex: TSex; // TSex — пол перечислимого типа;
FFirstName: строка;
Фластимя: строка;
//…
Общественный
свойство Пол: TSex чтение FSex запись FSex;
свойство FirstName: чтение строки FFirstName запись FFirstName;
свойство LastName: строка чтения FLastName записи FLastName;
//…
конец;
Затем для указателя Person типа TPerson вы можете использовать следующий код, чтобы определить, доступен ли указатель:
Пытаться
Человек.Пол;
//Или Person.FirstName;
//Или Person.LastName;
результат := True //Указатель доступен;
Кроме
результат := False;//Указатель недоступен
конец;
То, что мы обсуждали выше, является лишь технической возможностью. Я хочу подчеркнуть, что даже если есть хороший способ сделать это, не рекомендуется делать это часто. Потому что программа со строгой логикой должна иметь возможность предотвратить доступ к недействительному указателю.
Еще статьи