Recientemente, vi a un internauta preguntando en Internet: ¿Cómo determinar si un puntero de objeto está disponible? En otras palabras, ¿cómo determinar si un puntero de objeto apunta a una instancia de objeto real utilizable? En realidad esto no debería ser un problema. Porque el programador debería poder controlar su programa para que no acceda a un puntero no válido, porque la creación y destrucción de todas las instancias de objetos están bajo su control. E incluso si no hay una forma directa de determinar si el puntero del objeto está disponible, también se puede hacer a través de otras formas indirectas (como usar algunos identificadores, etc.) (por ejemplo, cuando destruimos una instancia de objeto, configuramos el el puntero del objeto al que apunta es nulo). Pero si dejamos de lado los dos puntos mencionados anteriormente y simplemente estudiamos si hay una manera de determinar si un puntero a objeto está disponible en Delphi, ¿qué pasará?
En Object Pascal, una clase puede tener dos tipos de métodos, uno se llama método de objeto (Método de objeto) y el otro es método de clase (Método de clase). El llamado método de objeto significa que la definición del método es para un objeto (o instancia), por lo que la llamada al método debe basarse en un objeto (o instancia). Por ejemplo, el destructor Destruir de una clase es un objeto. método (de hecho, a menudo La mayoría de los métodos utilizados son métodos de objetos). El método de clase se refiere a la definición del método en función de una clase de objetos, por lo que la llamada al método no necesita basarse en una instancia de objeto específica, como el constructor Crear de la clase. Esto tiene algo de inspiración para nosotros. La determinación de si un puntero de objeto está disponible parece lograrse mediante los siguientes pasos. Primero, podemos determinar si el puntero del objeto es nulo. Si es así, hemos terminado y definitivamente no está disponible; de lo contrario, intente ejecutar un método de objeto del objeto para ver si hay excepciones, como un acceso no válido a la memoria; Esto se utiliza para determinar si el objeto está disponible. Utilice el siguiente código para verificar nuestra idea:
var
Objeto: TObjeto;
comenzar
Obj := TObject.Create; //1.
Obj.Free; // 2. Libere el objeto recién creado y la memoria se recicla en este momento.
Si Obj = nil entonces //3. Determinar si el puntero está vacío (este paso a menudo no tiene éxito porque el objeto
//se libera, Delphi no vaciará automáticamente el puntero del objeto)
ShowMessage('El puntero de objeto no está disponible.')
demás
comenzar
Intentar
Si Obj.ClassType = TObject entonces //4. Llamar a un método de objeto de TObject.
ShowMessage('El tipo de objeto es TObject');
Excepto
ShowMessage('El puntero de objeto no está disponible.')
Fin;
fin;
fin;
Al ejecutar el código anterior, encontramos que Obj.ClassType todavía está disponible incluso si se ha ejecutado Obj.Free. Esto muestra que no todos los métodos de objetos deben depender de una instancia de objeto para ser accesibles. La razón es que este método de objeto no necesita acceder a la memoria solicitada por una instancia de objeto. En este sentido, el método TObject.ClassType no parece un método de objeto real, sino que se parece a un método de clase.
Al ejecutar el código anterior, también podemos encontrar que cuando un objeto ejecuta el método Free, solo libera toda la memoria que solicitó cuando se creó, pero no afecta el valor del puntero del objeto en sí. El puntero del objeto todavía apunta a la dirección de memoria original. Al mismo tiempo, debido a las particularidades de la implementación de algunos métodos de objeto (como ClassType), incluso si el objeto se ha liberado, el resultado de la llamada al método de objeto sigue siendo correcto.
En resumen, podemos sacar una conclusión, es decir, si un puntero de objeto puede juzgarse como disponible depende de si la clase a la que pertenece el puntero de objeto proporciona una forma de acceder a la memoria de la instancia del objeto; de esta manera, los métodos también pueden ser propiedades. Entonces, ¿cuál es la situación actual específicamente en cada categoría?
TObject, esta clase es la clase ancestral de todas las clases, no hay forma de emitir un juicio.
TPersistent, derivado de TObject, no necesita solicitar memoria adicional al crear una instancia de objeto, por lo que no hay forma de juzgar.
TComponent, derivado de TPersistent, agrega muchas propiedades que requieren que se aplique memoria adicional al crear una instancia de objeto, por lo que, en teoría, se juzga. El código es el siguiente:
función ComponentExists (AComponent: TComponent): booleano;
comenzar
intentar
AComponent.Hasparent; //Nota: esta oración también puede ser "AComponent.Tag;"
//O "AComponente.Nombre"
resultado: = Verdadero;
excepto
resultado := Falso;
fin;
fin;
Al llamar a ComponentExists, podemos saber si un puntero de objeto de tipo TComponent está disponible, independientemente de si el puntero de objeto se ha liberado o se ha establecido en cero.
Para otras clases, como TControl, TWinControl o TButton, etc., siempre que se deriven de TComponent, el método de evaluación de TComponent aún se aplica.
Hay otras clases definidas por el usuario, si se derivan directamente de clases que no se pueden juzgar (como TObject y TPersistent), pero no hay atributos que requieran aplicación de memoria durante la creación de instancias, entonces no hay forma de juzgar de lo contrario; es posible. Según un ejemplo:
Supongamos que tenemos una clase TPerson definida de la siguiente manera:
TPersona = Clase(TOobjeto)
Privado
FSex: TSex; // TSex es el género del tipo de enumeración;
FFirstName: Cadena;
FLastName: Cadena;
//…
Público
propiedad Sexo: TSex leer FSex escribir FSex;
propiedad FirstName: cadena lee FFirstName escribe FFirstName;
propiedad Apellido: Cadena lee FLastName escribe FLastName;
//…
fin;
Luego, para el puntero Persona de tipo TPerson, puede usar el siguiente código para determinar si el puntero está disponible:
Intentar
Persona.Sexo;
//O Persona.PrimerNombre;
//O Persona.Apellido;
resultado := Verdadero; //El puntero está disponible
Excepto
resultado := False;//El puntero no está disponible
fin;
Lo que comentamos anteriormente es sólo una posibilidad técnica. El punto que quiero enfatizar es que incluso si existe una buena manera de hacerlo, no se recomienda hacerlo con frecuencia. Porque un programa con lógica estricta debería poder impedir el acceso a un puntero no válido.
Más artículos