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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

Verifier si une classe est instanciee


Sujet :

Delphi

  1. #1
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 491
    Points : 245
    Points
    245
    Par défaut Verifier si une classe est instanciee
    Bonjour,

    Je fais un petit programme qui permet d'afficher des graphes a L’écran.
    Pour cela j'ai une classe qui étend un Panel, sur lequel je dessine avec un TBitmap et Canvas.

    Pas de problème avec cette classe, mais avec le contexte d'utilisation.
    Ma classe partage le Panel avec d'autre classe qui font la même chose avec une présentation différente
    et je dois pouvoir passer d'une représentation a l'autre.

    Pour cela je détruit l'instance précédente et je fais une nouvelle instance de la classe désirée
    ,qui est alors affichée.

    Pour revenir en arrière avec un événement je veux vérifier si l'instance de la classe détruite existe encore.

    Est-ce que cela est possible?

    Merci pour vos réponses

    PS: entre temps j'ai trouvé assigned, mais cela ne détecte pas la destruction de la classe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if Assigned(buy_down_chart)
              then ShowMessage('L instance existe')
              else ShowMessage('L instance existe pas');
    Le Destructeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    // Appel du destructeur
     buy_down_chart.Destroy;
     
    // Destructeur
    destructor TBuyDownChart. Destroy;
     
       begin
       FPaintBitmap. Free;
       FPaintBoxMain. Free;
       FPopupMenu. Free;
     
       inherited Destroy;
       end;
    L'instance ne devrait plus être répertoriée, non?

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    N'appele jamais Destroy !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Appel du destructeur
     buy_down_chart.Free();
    Extrait de l'aide :
    N'appelez pas directement Destroy. Appelez plutôt Free. Free vérifie que la référence objet n'a pas la valeur nil avant d'appeler Destroy.


    Utilise systématiquement FreeAndNil pour que le Assigned fonctionne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // Appel du destructeur
     buy_down_chart.Free();
     buy_down_chart := nil;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // Destructeur
    destructor TBuyDownChart.Destroy();
    begin
       FreeAndNil(FPaintBitmap);
       FreeAndNil(FPaintBoxMain);
     
       FPopupMenu.Free();
       FPopupMenu := nil; // à l'ancienne en Delphi 3-4 avant que FreeAndNil apparaisse
     
       inherited Destroy();
    end;
    tu peux aussi te crée une fonction RealAssigned mais juste comme outil de debug pour voir où tu as oublié
    j'avais fait une fonction RealAssigned qui vérifie qu'un objet existe (vérification de ClassName, ClassType, IsBadReadPtr)

    cela ressemblait à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function RealAssigned(Obj: TObject): Boolean;
    begin
      try
        Result := Obj.ClassType().ClassName = Obj.ClassName();
      except
        Result := False;
      end;
    end;
    Si tu as des difficultés à trouver tes objets non nil, utilise RealAssigned le temps de nettoyer le code !
    Normalement, un code bien conçu n'en a pas besoin !

    je l'avais créer pour trouver les Query instanciées et jamais libérer dans un projet
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 491
    Points : 245
    Points
    245
    Par défaut
    Merci pour la réponse, aussi vite ç’a fait toujours plaisir.

    Je vais essayer comme cela.

    @+

    marc_3

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    pour comprend facilement les choses il suffit de se faire un idée un peu grossière mais pas si éloignée de la réalité pour avoir les idées claires :

    imaginons que la mémoire de l'application soit un gros tableau

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    var
      memoire: array[0..4bg] of Byte;
    quand on alloue une zone mémoire, elle vient occuper un certain nombre d'octets en mémoire, l'adresse du premier des octes suffit pour localiser la variable car l'allocation utilise des octets contigus en mémoire.

    l'adresse de la variable c'est tout simplement l'index du premier octet qu'elle occupe dans le tableau "memoire".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    begin
      Panel1 := TPanel.Create(Self);
    end;
    la variable Panel1 contient donc l'emplacement de l'objet dans la mémoire.

    quand je copie la variable, je ne fais que copier l'adresse et non les données en mémoire qui n'ont pas bougé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    begin
      Panel2 := Panel1; // simple copie de l'index "panel1" vers l'index "panel2"
    end;
    l'appel au destructor var libérer l'espace mémoire occupé par le panneau dans la zone "mémoire", sans pour autant changer les variables "panel1" et "panel2" qui contiendront toujours l'index obtenu par le create.

    c'est comme dans le code ci-dessous

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    var
      tab: array[0..10] of string;
      s1 : Integer;
      s2 : Integer;
    begin
      s1 := 5;
      tab[s1] := 'Hello';
      s2 := s1;
      tab[s2] := '';
    // ici s1 et s2 valent toujours 5 alors que tab[5] est vide
    // on peut forcer les valeurs de s1 et s2 pour noter cet état
      s1 := -1;
      s2 := -1;
    end;
    on a le même phénomène avec des objects

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var
      p1, p2: TPanel;
    begin
      p1 := TPanel.Create(nil);
      p2 := p1;
      p2.Free;
    // p1 et p2 contiennent toujours l'adresse qu'occupait le Panel alors que celui-ci n'existe plus
    // on peut forcer les valeurs de p1 et p2 pour noter cet état
      p1 := nil;
      p2 := nil;
    end;
    la fonction FreeAndNil() comme son nom l'indique fait un Free et donne la valeur "nil" à la variable passée en paramètre.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Membre actif
    Inscrit en
    Décembre 2003
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 491
    Points : 245
    Points
    245
    Par défaut
    Merci pour le complement.
    Pour moi l'idee est deja claire, ce qui ne l'est pas du tout c'est ce qui se passe en arriere plan cote interpretation de la commande Free.

    Apparement il y avait une ambiquite, car sinon pourquoi devoir creer plus tard la commande FreeandNil pour lever
    l'ambiquite en question.

    Merci pour la demo

    marc_3

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Citation Envoyé par Marc_3 Voir le message
    Pour moi l'idee est deja claire, ce qui ne l'est pas du tout c'est ce qui se passe en arriere plan cote interpretation de la commande Free.
    Il n'y a pas vraiment d'ambiguïté mais plutôt une confusion fréquente chez les développeurs

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var
      Obj: TForm;
    begin
      Obj := TForm.Create(nil);
    Beaucoup font la confusion sur ce qui forme une instance de classe ou autrement dit un objet en Delphi :
    - une référence d'objet, une sorte de pointeur contenu dans Obj.
    - la zone mémoire pointée par la référence d'objet qui contient les données que l'on pourrait exprimer avec la syntaxe de pointeur Obj^ mais évidemment cela n'existe pas en Delphi !

    En C++Builder c'est bien plus visible puisque l'on déclare ainsi
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      TForm * Obj;
      Obj = new TForm(nil);
    ou même
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
      TForm * Obj = new TForm(nil);

    Pour une méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Obj.Show(); // en Delphi, la référence d'objet transparent, d'ailleurs même sur un pointeur de record, le déférencement est implicite avec l'opérateur .
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (Obj*).Show(); // syntaxe C, déférencement puis accès au membre, en C ce n'était que les struct, en C++ cela fonctionne sur struct et class
    Obj->Show(); // syntaxe C++ avec l'opérateur combiné -> et cela fonctionne sur struct et class


    Après le Free, la zone mémoire pointée par l'objet qui est libérée, cela permet au gestionnaire de mémoire d'y mettre autre chose à place,
    cela peut même libérer un bloc totalement et c'est l'OS qui pourrait en faire ce qu'il veut.

    le Free est un équivalent à un Dispose(Obj) ou FreeMem(Obj)En fait le Destroy est une méthode "magique" dont on a pas le code (c'est dans le compilateur qui le génère)
    qui fait appel à BeforeDestruction puis à _ClassDestroy qui appel FreeInstance

    Par contre la variable Obj contient toujours la référence de l'objet et cela pointe maintenant sur une zone non allouée de la mémoire

    Si l'on faisait un équivalent du déférencement genre Obj^,
    on pourrait même y retrouver des données tel que les types simples comme Integer, Double... si l'on pas une violation d'accès évidemment !
    par contre les array, les string sont purgés ainsi que les données liés à la VMT,
    voir Formats de données internes (Delphi) - Types classe


    l'affectation à nil ou l'utilisation de FreeAndNil permet juste de vider la variable,
    en "oubliant" la référence on ne pointe nulle part au lieu de conserver un pointeur invalide
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Marc_3 Voir le message
    Merci pour le complement.
    Pour moi l'idee est deja claire, ce qui ne l'est pas du tout c'est ce qui se passe en arriere plan cote interpretation de la commande Free.

    Apparement il y avait une ambiquite, car sinon pourquoi devoir creer plus tard la commande FreeandNil pour lever
    l'ambiquite en question.

    Merci pour la demo

    marc_3
    mes explications ne sont donc pas claires puisqu'elles sont supposées répondre justement à ce point précis

    NB: Free ne peux en aucun cas modifier la variable qui permet son appel !
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/06/2006, 17h13
  2. Vérifier qu'une variable est un nombre
    Par GLDavid dans le forum Linux
    Réponses: 9
    Dernier message: 13/02/2006, 16h06
  3. [POO] Classe interne à une classe, est ce possible ?
    Par Matth_S dans le forum Langage
    Réponses: 13
    Dernier message: 10/02/2006, 10h24
  4. Réponses: 2
    Dernier message: 17/08/2005, 14h40
  5. verifier si une url est exacte
    Par romuluslepunk dans le forum Applets
    Réponses: 14
    Dernier message: 16/08/2005, 16h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo