IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ PascalConsultez toutes les FAQ

Nombre d'auteurs : 10, nombre de questions : 402, dernière mise à jour : 7 janvier 2018  Ajouter une question

 

Bienvenue dans la F.A.Q. Pascal !

Celle-ci rassemble les réponses aux questions les plus fréquemment posées sur le langage Pascal et tous ses outils de programmation. Si elle n'a pas pour vocation de répondre à toutes les interrogations possibles, elle reste une bonne base de connaissances sur le Pascal, et ne demande qu'à être enrichie par vos expériences personnelles.

Nous vous invitons à proposer vos propres questions/réponses directement dans la FAQ ou, si vous souhaitez apporter une modification à une question/réponse existante, à la poster dans le fil de discussion renseigné ci-dessous.

Nous vous souhaitons une bonne lecture !

L'équipe Pascal.

SommaireLes différents compilateursFree PascalFree Pascal et la Programmation Orientée ObjetCréation et libération (12)
précédent sommaire suivant
 

Un objet en tant qu'instance de classe occupe de la mémoire qu'il faut allouer sur le tas (heap) avant toute utilisation le concernant. Un constructeur (constructor) est précisément une méthode spéciale qui permet cette allocation de mémoire tout en renvoyant un pointeur vers l'objet créé.

En général, cette méthode particulière s'appelle Create, mais ce nom est arbitraire. En revanche, sa déclaration commencera toujours par le mot réservé constructor. Il peut exister plusieurs constructeurs avec autant de paramètres que nécessaires.

Voici le code pour la création de l'objet MyObjde type TMyClasssi l'un de ses constructeurs s'appelle Createet ne prend aucun paramètre :

Code pascal : Sélectionner tout
1
2
  
  MyClass := TMyClass.Create;

N.B. : C'est toujours en mentionnant le nom de la classe (ici, TMyClass) que l'on crée un objet.

Mis à jour le 17 août 2016 gvasseur58

Il peut arriver aussi que vous ayez besoin de plusieurs constructeurs pour une même classe. Dans ce cas, c'est la directive overload qui sera utile puisqu'elle permet des homonymes aux paramètres différents.

Code pascal : Sélectionner tout
1
2
3
4
5
6
7
type 
  
  TMyClass = class 
  public 
    constructor Create; overload; 
    constructor Create(const ASt: string); overload; 
  end;

Mis à jour le 19 août 2016 gvasseur58

Il est exceptionnel de ne pas avoir à surcharger un constructeur : la plupart du temps, il faut initialiser des champs à des valeurs spécifiques ou instancier certaines classes qui serviront d'outils. Mais il faut aussi conserver d'éventuelles initialisations des constructeurs des ancêtres, d'où la nécessité d'employer inherited.

Si vous voulez modifier le comportement des parents, il est généralement nécessaire d’appeler en premier lieu inherited puis d’apporter les modifications.

Code pascal : Sélectionner tout
1
2
3
4
5
6
constructor Create; 
begin 
  inherited Create; // on hérite 
// ensuite votre travail d’initialisation 
// [...] 
end;

Mis à jour le 19 août 2016 gvasseur58

En cas d'erreur lors de l'instanciation, le destructeur Destroy correspondant est automatiquement appelé.
La conséquence majeure de ce mécanisme est qu'il ne faut pas protéger le code de l'instanciation au risque d'essayer de libérer plusieurs fois des ressources :

Code pascal : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// code fautif 
  
try 
  MyObj := TMyClass.Create; 
  MyObj.DoSomething; 
finally 
  MyObj.Free; 
end; 
  
// code correct 
  
MyObj := TMyClass.Create; 
try 
  MyObj.DoSomething; 
finally 
  MyObj.Free; 
end;

Mis à jour le 19 août 2016 gvasseur58

Comme un objet occupe de la place en mémoire, il est nécessaire de la libérer après usage. Cette libération peut être automatique dans certains cas (comme avec des composants posés sur une fiche), mais demande la plupart du temps une action explicite du programmeur. C'est cette libération de la mémoire que réalise un destructeur.

Le destructeur (destructor) est une méthode particulière dont le nom est toujours Destroy. Il est déclaré avec le mot réservé destructoret ne ne comporte aucun argument.

Voici un exemple de déclaration d'un destructeur :

Code pascal : Sélectionner tout
1
2
3
4
5
6
TMyClass = class 
  [...] 
  public 
    constructor Create(AValue: Integer); 
    destructor Destroy; override; 
end;

Le destructeur n'est pas appelé directement, mais via la méthode Free. On surcharge le destructeur afin d'être sûr de ne pas oublier d’appeler le destructeur des ancêtres de la classe en question.

Mis à jour le 17 août 2016 gvasseur58

Quand vous n'avez plus besoin d'un objet, il est nécessaire de le détruire, sinon vous obtiendrez ce qu'on appelle des fuites de mémoire : la mémoire allouée à votre objet ne sera pas libérée par le système.

Pour le libérer, il suffit d'appeler la méthode Freequi fera le travail nécessaire.

Exemple :

Code pascal : Sélectionner tout
1
2
3
4
5
6
7
8
var 
  MyClass: TMyClass; 
[...] 
  MyClass := TMyClass.Create; 
  [...] 
  MyClass.DoSomething; 
  [...] 
  MyClass.Free;

N.B. : la méthode Freeest disponible dès l'instanciation de votre classe.

Mis à jour le 10 août 2016 gvasseur58

Pour Destroy, le schéma suivant s’applique : procédez en premier lieu à votre travail local de nettoyage (en général, la libération d'objets créés par votre classe pour ses besoins propres) puis héritez de l'ancêtre. Sinon, vous risquez par exemple de vouloir libérer des ressources qui auront déjà été libérées par un ancêtre de votre classe et par conséquent de provoquer une erreur.

La forme habituelle du destructeur Destroy hérité sera donc :

Code pascal : Sélectionner tout
1
2
3
4
5
6
destructor Destroy; 
begin 
  // votre travail local de nettoyage 
  // [...] 
  inherited Destroy; // on hérite ensuite ! 
end;

Mis à jour le 19 août 2016 gvasseur58

Il peut sembler paradoxal de renseigner la méthode Destroy pour détruire un objet, mais d'appeler la méthode Free pour le faire.

En fait, la méthode Free vérifie l'existence de l'objet avant de la le détruire, ce qui évite de déclencher une erreur si l'objet n'a pas été créé correctement : en effet, comment détruire un objet qui n'a pas été créé ? Après cette vérification, Free appelle Destroy.

Mis à jour le 10 août 2016 gvasseur58

Nilest la valeur attribuée à un objet lorsqu'il n'a pas encore été créé. Il est ainsi possible de tester la valeur de la variable renvoyant à l'hypothétique objet.

Code pascal : Sélectionner tout
1
2
3
4
5
6
var 
  MyObj: TMyClass; 
[...] 
  
if MyObj = nil then 
  MyObj := TMyClass.TCreate;

N.B. : un équivalent de ce test est l'emploi de la méthode Assigned.
On peut par conséquent écrire :

Code pascal : Sélectionner tout
1
2
3
4
5
6
var 
  MyObj: TMyClass; 
[...] 
  
if not Assigned(MyObj) then 
  MyObj := TMyClass.TCreate;

Mis à jour le 10 août 2016 gvasseur58

Il peut être tentant de libérer un objet en lui affectant la valeur Nilpuisqu'elle correspond à un objet non affecté. Malheureusement, cette affectation ne libèrera pas la mémoire allouée à l'objet : il faut par conséquent utiliser la méthode Freeou la procédure FreeAndNil.

N.B. : comme son nom l'indique FreeAndNillibère en premier lieu l'objet puis met à Nilsa valeur.

Mis à jour le 10 août 2016 gvasseur58

Afin de s'assurer que la mémoire allouée à une instance de classe sera toujours libérée, il suffit d'utiliser try...finally.

Exemple :

Code pascal : Sélectionner tout
1
2
3
4
5
6
7
8
9
var 
  MyObj: TMyClass; 
[...] 
  MyObj := TMyClass.Create; 
  try 
    MyObj.DoSomething; 
  finally 
    MyObj.Free; 
  end;

N.B. : La création de l'objet a lieu en dehors de la section protégée, car en cas d'échec de Create, la mémoire pour l'objet n'est pas réservée.

Mis à jour le 10 août 2016 gvasseur58

Si vous pensez réutiliser une variable référençant une instance de classe libérée, en lieu et place de Free, utilisez la procédure FreeAndNil définie dans SysUtils qui à la fois libère l'instance comme Free, mais aussi place la valeur nil dans le pointeur sur cette instance.

De cette manière, la méthode Assigned ne sera pas leurrée par la destruction d'un objet qui ne réinitialise pas la référence à cette instance !

Au lieu de :

Code pascal : Sélectionner tout
MyObj.Free;

vous pouvez uitliser

Code pascal : Sélectionner tout
FreeAndNil(MyObj);

N.B. : L'utilisation de la procédure FreeAndNil est déconseillée par certains, car elle est souvent le signe d'une mauvaise conception d'un programme : une instance libérée ne devrait jamais être réutilisée.

Mis à jour le 19 août 2016 gvasseur58

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.