Recentemente, vi um internauta perguntando na Internet: Como determinar se um ponteiro de objeto está disponível? Em outras palavras, como determinar se um ponteiro de objeto aponta para uma instância de objeto real utilizável? Na verdade, isso não deve ser um problema. Porque para o programador ele deve ser capaz de controlar seu programa para não acessar um ponteiro inválido, pois a criação e destruição de todas as instâncias do objeto estão sob seu controle. E mesmo que não haja uma maneira direta de determinar se o ponteiro do objeto está disponível, isso também pode ser feito através de outras formas indiretas (como usar alguns identificadores, etc.) (por exemplo, quando destruímos uma instância do objeto, definimos o ponteiro do ponteiro do objeto é nulo). Mas se deixarmos de lado os dois pontos mencionados acima e apenas estudarmos se existe uma maneira de determinar se um ponteiro de objeto está disponível no Delphi, o que acontecerá?
Em Object Pascal, uma classe pode ter dois tipos de métodos, um é chamado de método de objeto (Método de Objeto) e o outro é método de classe (Método de Classe). O chamado método de objeto significa que a definição do método é para um objeto (ou instância), portanto, a chamada do método precisa ser baseada em um objeto (ou instância). Por exemplo, o destruidor Destroy de uma classe é um objeto. método (na verdade, muitas vezes a maioria dos métodos usados são métodos de objeto). O método de classe refere-se à definição do método com base em uma classe de objetos, portanto, a chamada do método não precisa ser baseada em uma instância específica do objeto, como o construtor Create da classe. Isso tem alguma inspiração para nós. Determinar se um ponteiro de objeto está disponível parece ser realizado através das etapas a seguir. Primeiro, podemos determinar se o ponteiro do objeto é nulo. Em caso afirmativo, terminamos e, caso contrário, ele está definitivamente indisponível, tente executar um método de objeto do objeto para ver se há exceções, como acesso à memória inválido; Isso é usado para determinar se o objeto está disponível. Use o seguinte código para verificar nossa ideia:
var
Obj: TObject;
começar
Obj := TObject.Create; //1.
Obj.Free; //2. Libera o objeto recém-criado e a memória é reciclada neste momento.
Se Obj = nil então //3 Determine se o ponteiro está vazio (esta etapa geralmente não é bem-sucedida porque o objeto.
//é liberado, o Delphi não esvaziará automaticamente o ponteiro do objeto)
ShowMessage('O ponteiro do objeto não está disponível.')
outro
começar
Tentar
Se Obj.ClassType = TObject então //4.
ShowMessage('O tipo de objeto é TObject');
Exceto
ShowMessage('O ponteiro do objeto não está disponível.')
Fim;
fim;
fim;
Executando o código acima, descobrimos que Obj.ClassType ainda está disponível mesmo que Obj.Free tenha sido executado. Isso mostra que nem todos os métodos de objeto devem depender de uma instância de objeto para serem acessíveis. A razão é que este método de objeto não precisa acessar a memória solicitada por uma instância de objeto. Nesse sentido, o método TObject.ClassType não se parece com um método de objeto real, mas sim com um método de classe.
Executando o código acima, também podemos descobrir que quando um objeto executa o método Free, ele apenas libera toda a memória solicitada quando foi criado, mas não afeta o valor do ponteiro do objeto em si. O ponteiro do objeto ainda aponta para o endereço de memória original. Ao mesmo tempo, devido à particularidade da implementação de alguns métodos de objeto (como ClassType), mesmo que o objeto tenha sido lançado, o resultado da chamada do método do objeto ainda está correto.
Resumindo, podemos tirar uma conclusão, ou seja, se um ponteiro de objeto pode ser julgado como disponível depende se a classe à qual o ponteiro de objeto pertence fornece uma maneira de acessar a memória da instância do objeto - desta forma pode ser Métodos também podem sejam propriedades. Então, qual é a situação agora especificamente em cada categoria?
TObject, esta classe é a classe ancestral de todas as classes, não há como fazer um julgamento.
TPersistent, derivado de TObject, não precisa solicitar memória adicional ao criar uma instância de objeto, portanto não há como julgar.
TComponent, derivado de TPersistent, adiciona muitas propriedades que requerem memória adicional para serem aplicadas ao criar uma instância de objeto, portanto, em teoria, ele é julgado. O código é o seguinte:
função ComponentExists(AComponent: TComponent): Boolean;
começar
tentar
AComponent.Hasparent; //Nota: Esta frase também pode ser "AComponent.Tag;"
//Ou "AComponent.Nome"
resultado := Verdadeiro;
exceto
resultado := Falso;
fim;
fim;
Chamando ComponentExists, podemos saber se um ponteiro de objeto do tipo TComponent está disponível, independentemente de o ponteiro de objeto ter sido liberado ou definido como nulo.
Para outras classes, como TControl, TWinControl ou TButton, etc., desde que sejam derivadas de TComponent, o método de julgamento de TComponent ainda se aplica.
Existem outras classes definidas pelo usuário, se forem derivadas diretamente de classes que não podem ser julgadas (como TObject e TPersistent), mas não há atributos que exijam aplicação de memória durante a instanciação, então não há como julgar; é possível. Segundo um exemplo:
Suponha que temos uma classe TPerson definida da seguinte forma:
TPPessoa = Classe(TObject)
Privado
FSex: TSex; // TSex é o gênero do tipo de enumeração;
FPrimeiroNome: String;
Sobrenome: String;
//…
Público
propriedade Sexo: TSex lê FSex escreve FSex;
propriedade Nome: String lida FFirstName escreve FFirstName;
propriedade Sobrenome: String lida FLastName escreve FLastName;
//…
fim;
Então, para o ponteiro Person do tipo TPerson, você pode usar o código a seguir para determinar se o ponteiro está disponível:
Tentar
Pessoa.Sexo;
//Ou Person.FirstName;
//Ou Pessoa.Sobrenome;
resultado := True; //O ponteiro está disponível
Exceto
resultado := False;//O ponteiro não está disponível
fim;
O que discutimos acima é apenas uma possibilidade técnica. O ponto que quero enfatizar é que mesmo que exista uma boa maneira de fazer isso, não é incentivado fazê-lo com frequência. Porque um programa com lógica estrita deve ser capaz de impedir o acesso a um ponteiro inválido.
Mais artigos