Chapitre 3 terminé, gestion des exceptions et des erreurs, extrait
Constructeurs et exceptions
Ce sujet est souvent évoqué dans la communauté C++, mais personne ne semble y avoir prêté attention dans la communauté Delphi. Peut-être en raison des caractéristiques du langage, les programmeurs Delphi n'ont pas à se soucier de ce problème. Mais je pense que les programmeurs Delphi devraient également comprendre ce problème et savoir ce que le langage nous offre pour nous permettre de l'ignorer si facilement. Comme le dit le proverbe : « Lorsque vous êtes entouré de bénédictions, vous devez connaître les bénédictions ». Nous savons que le constructeur d'une classe n'a pas de valeur de retour. Si le constructeur ne parvient pas à construire l'objet, il est impossible de compter sur le retour d'un code d'erreur. Alors, comment identifier l'échec du constructeur dans le programme ? La méthode la plus « standard » est la suivante : lever une exception. L'échec du constructeur signifie que la construction de l'objet échoue. Ainsi, après qu'une exception soit levée, comment cet objet « à moitié mort » sera-t-il géré ? Ici, je pense qu'il est nécessaire de comprendre comment C++ gère cette situation avant de lire. En C++, le destructeur n’est pas appelé après que le constructeur a levé une exception. Cette approche est raisonnable car l’objet n’est pas encore complètement construit. Si le constructeur a effectué certaines opérations telles que l'allocation de mémoire, l'ouverture de fichiers, etc., alors la classe C++ doit avoir ses propres membres pour se souvenir des actions qui ont été effectuées. Bien sûr, cela est très gênant pour les implémenteurs de classe, donc généralement les implémenteurs de classe C++ évitent de lancer des exceptions dans les constructeurs (vous pouvez fournir une fonction membre telle que Init et UnInit, qui est laissée au constructeur ou au client de classe pour la gérer). échec d'initialisation). La solution fournie par chaque livre classique en C++ consiste à utiliser des pointeurs intelligents (classe standard auto_ptr de STL). En Pascal Objet, ce problème devient très simple et les programmeurs n'ont pas à s'en soucier. Si une classe Object Pascal lève une exception dans le constructeur, le compilateur appellera automatiquement le destructeur de la classe (puisque le destructeur n'est pas autorisé à être surchargé, il est garanti qu'il n'y a qu'un seul destructeur, donc le compilateur ne sera pas confus . parmi plusieurs destructeurs). Les objets membres sont généralement détruits dans le destructeur, et la méthode Free() garantit que le destructeur ne sera pas appelé sur des objets nuls (c'est-à-dire des objets membres qui n'ont pas encore été créés). Par conséquent, tout en rendant le code concis et beau, il assure également la sécurité. tapez MyClass = classPRivateFStr : PChar; // Pointeur de chaîne publicconstructor Create();destructor Destroy(); override;end;constructor MyClass.Create();beginFStr := StrAlloc(10); // Pointeur de chaîne dans le constructeur Allouer de la mémoire StrCopy (FStr, 'ABCDEFGHI'); lever Exception.Create('erreur'); Lancement d'une exception, aucune raison, hahaend;destructor A.Destroy();beginStrDispose(FStr); // Libère la mémoire dans le destructeur WriteLn('Free Resource');end;varObj : TMyClass;i : integer;begintryObj : = TMyClass.Create ();Obj.Free();WriteLn('Réussi');saufObj := nil;WriteLn('Failed');end;Read(i); // Suspend l'écran pour observer la fin des résultats en cours d'exécution. Dans ce code, le constructeur lève une exception et le résultat de l'exécution est : Free ResourceFailed à ce moment-là. La sortie Free Resource" est produite par le compilateur appelant automatiquement le destructeur. Par conséquent, si la documentation de la classe ou l'auteur de la classe vous indique que le constructeur de la classe peut lever une exception, n'oubliez pas de l'envelopper avec try...sauf ! Les différentes façons dont C++ et Object Pascal traitent les exceptions levées par les constructeurs sont en fait l'incarnation des idées de conception des deux langages. C++ adhère au style du C et se concentre sur l’efficacité. Tout est laissé au programmeur et le compilateur n’effectue aucune action inutile. Object Pascal hérite du style de Pascal et se concentre sur la signification esthétique du programme. Le compilateur aide les programmeurs à réaliser un travail complexe.