Récemment, j'ai vu un internaute demander sur Internet : Comment déterminer si un pointeur d'objet est disponible ? En d’autres termes, comment déterminer si un pointeur d’objet pointe vers une instance d’objet réelle et utilisable ? En fait, cela ne devrait pas poser de problème. Car pour le programmeur, il doit pouvoir contrôler son programme pour ne pas accéder à un pointeur invalide, car la création et la destruction de toutes les instances d'objet sont sous son contrôle. Et même s'il n'existe pas de moyen direct de déterminer si le pointeur d'objet est disponible, cela peut également être fait par d'autres moyens indirects (comme l'utilisation de certains identifiants, etc.) (par exemple, lorsque nous détruisons une instance d'objet, nous définissons le le pointeur de l'objet sur lequel le pointeur est nul). Mais si nous mettons de côté les deux points mentionnés ci-dessus et étudions simplement s'il existe un moyen de déterminer si un pointeur d'objet est disponible dans Delphi, que se passera-t-il ?
En Pascal Objet, une classe peut avoir deux types de méthodes, l'une est appelée méthode objet (Méthode Objet) et l'autre est méthode de classe (Méthode Classe). La méthode dite objet signifie que la définition de la méthode concerne un objet (ou une instance), donc l'appel de la méthode doit être basé sur un objet (ou une instance). Par exemple, le destructeur Destroy d'une classe est un objet. (en fait, nous utilisons souvent la plupart des méthodes utilisées pour utiliser des méthodes objets). La méthode de classe fait référence à la définition de la méthode basée sur une classe d'objets, donc l'appel de la méthode n'a pas besoin d'être basé sur une instance d'objet spécifique, telle que le constructeur Create de la classe. Cela nous inspire. Déterminer si un pointeur d'objet est disponible semble être accompli par les étapes suivantes. Tout d'abord, nous pouvons déterminer si le pointeur d'objet est nul. Si c'est le cas, alors nous avons terminé et il est définitivement indisponible. Sinon, essayez d'exécuter une méthode objet de l'objet pour voir s'il existe des exceptions telles qu'un accès mémoire non valide. Ceci est utilisé pour déterminer si l'objet est disponible. Utilisez le code suivant pour vérifier notre idée :
var
Obj : TObject ;
commencer
Obj := TObject.Create; //1. Créer un objet
Obj.Free; //2. Libérez l'objet qui vient d'être créé, et la mémoire est recyclée à ce moment-là.
Si Obj = nil alors //3. Déterminez si le pointeur est vide (cette étape échoue souvent car l'objet
//est libéré, Delphi ne videra pas automatiquement le pointeur d'objet)
ShowMessage('Le pointeur d'objet n'est pas disponible.')
autre
commencer
Essayer
Si Obj.ClassType = TObject alors //4 Appelez une méthode objet de TObject.
ShowMessage('Le type d'objet est TObject');
Sauf
ShowMessage('Le pointeur d'objet n'est pas disponible.')
Fin;
fin;
fin;
En exécutant le code ci-dessus, nous constatons que Obj.ClassType est toujours disponible même si Obj.Free a été exécuté. Cela montre que toutes les méthodes objet ne doivent pas nécessairement dépendre d'une instance d'objet pour être accessibles. La raison en est que cette méthode objet n'a pas besoin d'accéder à la mémoire demandée par une instance d'objet. En ce sens, la méthode TObject.ClassType ne ressemble pas à une véritable méthode objet, mais plutôt à une méthode de classe.
En exécutant le code ci-dessus, nous pouvons également constater que lorsqu'un objet exécute la méthode Free, il libère uniquement toute la mémoire demandée lors de sa création, mais cela n'affecte pas la valeur du pointeur d'objet lui-même. Le pointeur d'objet pointe toujours vers l'adresse mémoire d'origine. Dans le même temps, en raison de la particularité de l'implémentation de certaines méthodes objet (comme ClassType), même si l'objet a été libéré, le résultat de l'appel de la méthode objet est toujours correct.
Pour résumer, nous pouvons tirer une conclusion, c'est-à-dire que la question de savoir si un pointeur d'objet peut être jugé comme disponible dépend du fait que la classe à laquelle appartient le pointeur d'objet fournit un moyen d'accéder à la mémoire de l'instance d'objet - cette méthode peut également être être des propriétés. Alors, quelle est la situation désormais spécifiquement dans chaque catégorie ?
TObject, cette classe est la classe ancêtre de toutes les classes, il n'y a aucun moyen de porter un jugement.
TPersistent, dérivé de TObject, n'a pas besoin de demander de la mémoire supplémentaire lors de la création d'une instance d'objet, il n'y a donc aucun moyen de juger.
TComponent, dérivé de TPersistent, ajoute de nombreuses propriétés qui nécessitent l'application de mémoire supplémentaire lors de la création d'une instance d'objet, donc en théorie, cela est jugé. Le code est le suivant :
fonction ComponentExists (AComponent : TComponent) : Booléen ;
commencer
essayer
AComponent.Hasparent; //Remarque : cette phrase peut également être "AComponent.Tag;"
//Ou "AComponent.Name"
résultat := Vrai ;
sauf
résultat := Faux;
fin;
fin;
En appelant ComponentExists, nous pouvons savoir si un pointeur d'objet de type TComponent est disponible, que le pointeur d'objet ait été libéré ou défini sur zéro.
Pour les autres classes, telles que TControl, TWinControl ou TButton, etc., tant qu'elles sont dérivées de TComponent, la méthode de jugement de TComponent s'applique toujours.
Il existe d'autres classes définies par l'utilisateur. Si elles sont directement dérivées de classes qui ne peuvent pas être jugées (telles que TObject et TPersistent), mais qu'aucun attribut ne nécessite une application de mémoire lors de l'instanciation, alors il n'y a aucun moyen de juger autrement ; est possible. D'après un exemple :
Supposons que nous ayons une classe TPerson définie comme suit :
TPerson = Classe (TObject)
Privé
FSex : TSex ; // TSex est le sexe du type d'énumération ;
FPremier : chaîne ;
FLastName : chaîne ;
//…
Publique
propriété Sexe : TSex lire FSex écrire FSex ;
propriété FirstName : chaîne lecture FFirstName écriture FFirstName ;
propriété LastName : chaîne lire FLastName écrire FLastName ;
//…
fin;
Ensuite, pour le pointeur Person de type TPerson, vous pouvez utiliser le code suivant pour déterminer si le pointeur est disponible :
Essayer
Personne.Sexe ;
//Ou Personne.Premier;
//Ou Person.LastName;
result := True; //Le pointeur est disponible
Sauf
result := False;//Le pointeur n'est pas disponible
fin;
Ce dont nous avons discuté ci-dessus n’est qu’une possibilité technique. Le point que je tiens à souligner est que même s’il existe une bonne façon de le faire, il n’est pas encouragé à le faire fréquemment. Parce qu'un programme avec une logique stricte devrait être capable d'empêcher l'accès à un pointeur invalide.
Plus d'articles