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

Contribuez Delphi Discussion :

Appeler la méthode Create indépendamment de constructeur


Sujet :

Contribuez Delphi

  1. #1
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut Appeler la méthode Create indépendamment de constructeur
    Voici trois méthodes démontre comment appeler la méthode Create indépendamment de constructeur

    Methode 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Getmem(B,TButton.InstanceSize);
    ZeroMem(B,TButton.InstanceSize);
    PInteger(B)^ := Integer(TButton);
    B.Create(Self);
    B.Parent:=Self;
    Methode 2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Getmem(B,TButton.InstanceSize);
    TButton.InitInstance(B);
    B.Create(Self);
    B.Parent:=Self;
    Methode 3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    B:=TButton.NewInstance;
    B.Create(Self);
    B.Parent:=Self;
    Standard
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B:=TButton.Create(Self);
    B.Parent:=Self;

  2. #2
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Salut

    merci MONTOR mais je crois que la méthode standard utilise elle même la 1ière technique, de même pour les deux autres méthodes qui, je crois, l'utilisent aussi.

    En plus, le défi des concepteur de Delphi était de mettre du code prêt à l'emploi pour les utilisateur des composants Delphi. Par contre, je crois, que les développeurs de composants sous Delphi doivent connaitre impérativement les techniques de base telle que celles que tu présentes.

    Cordialement.
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  3. #3
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    Oui effectivement c'est pour donner une idée et enlever la confusion autour de constructeur qui reste un peu flou pour certains et aussi pour répondre a l'obsession En réalité la Méthode 1 est déconseillée puisque les interfaces ne sont pas initiées mais explique la notion de instance

  4. #4
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Les méthodes 1 et 2 ne sont pas correctes, car elles ne prennent pas en compte que les objets peuvent avoir surchargé NewInstance.

    Pire, la méthode 1 est parfaitement fausse si la classe implémente au moins une interface (donc pour TButton c'est faux). C'est InitInstance qui se charge du boulot lié aux interfaces.

    La méthode 3 n'est pas exactement équivalente à la 4. Il faudrait écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    B := TButton(TButton.NewInstance);
    try
      B.Create(Self);
    except
      B.Destroy;
      raise;
    end;
     
    B.Parent := Self;
    Seule cette méthode peut être considérée comme une alternative valable. Mais son utilité est vraiment très rare. J'en ai un cas dans Sepi, mais c'est tout.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  5. #5
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Dans le genre, j'en ai une bien dégueulasse. À nouveau, utilisée une et une seule fois dans Sepi. Elle ne fonctionne que pour les classes qui n'ont pas surchargé Destroy depuis TObject.

    Le but étant de faire l'allocation de mémoire de l'objet sur la pile, et non sur le tas. Quand c'est la seule source d'allocation mémoire sur le tas dans un algorithme coûteux, ça peut améliorer sensiblement les performances. Mais c'est vraiment, vraiment à ne faire que dans des cas très rares !
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    type
      TMyObject = class(TObject)
        // ...
        constructor Create(AValue: Integer);
        // pas de destructor
      end;
     
    procedure DoSomething;
    var
      Size: Integer;
      Obj: TMyObject;
    begin
      Size := TMyObject.InstanceSize;
      asm
            SUB     ESP, Size
            MOV     Obj, ESP
      end;
     
      TMyObject.InitInstance(Obj);
      try
        Obj.Create(3);
        // Do something with object Obj
      finally
        Obj.CleanupInstance;
      end;
     
      asm
            ADD     ESP, Size
      end;
    end;
    Je n'ai pas testé, mais ceci devrait fonctionner dans le cas où Destroy a été surchargée :
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    type
      TMyObject = class(TObject)
        // ...
        constructor Create(AValue: Integer);
        destructroy Destroy; override;
      end;
     
    procedure DoSomething;
    var
      Size: Integer;
      Obj: TMyObject;
    begin
      Size := TMyObject.InstanceSize;
      asm
            SUB     ESP,Size
            MOV     Obj,ESP
      end;
     
      TMyObject.InitInstance(Obj);
      try
        Obj.Create(3);
         // Do something with object Obj
      finally
        asm
            MOV     EAX,Obj
            XOR     DL,DL
            MOV     ECX,[EAX]
            CALL    DWORD PTR [ECX + VMTOFFSET TObject.Destroy]
        end;
     
        Obj.CleanupInstance;
      end;
     
      asm
            ADD     ESP,Size
      end;
     end;
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  6. #6
    Membre éprouvé
    Avatar de Montor
    Homme Profil pro
    Autre
    Inscrit en
    Avril 2008
    Messages
    879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Avril 2008
    Messages : 879
    Points : 963
    Points
    963
    Par défaut
    Merci pour tes explications...bien sur il faut demander dans quelle contexte
    on peut faire une telle utilisation ... dans mon cas je voulais créer Array Of Instance que je le trouve mieux que de utiliser le memorymanager

  7. #7
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Oui effectivement, dans ce cas-là, tu ne peux pas les méthodes 3 ou 4. Mais c'est tout de même douteux

    En relisant le sujet je remarque qu'on a complètement oublié un détail d'importance jusqu'ici : l'appel de la méthode AfterConstruction !

    Normalement j'ai bien compris le mécanisme complet, et l'alternative complète au Create habituel serait :
    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
    16
    17
    18
    19
    20
    21
    22
    23
    B := TButton(TButton.NewInstance);
     
    try
      B.Create(Self);
     
      try
        B.AfterConstruction;
      except
        B.BeforeDestruction;
        raise;
      end;
    except
      CallDestroy(B, $81);
      raise;
    end;
     
    procedure CallDestroy(Obj: TObject; OuterMost: Shortint);
    asm
            { -> EAX  Pointer to instance
                 DL   Dealloc flag }
            MOV     ECX,[EAX]
            CALL    DWORD PTR [ECX + VMTOFFSET TObject.Destroy]
    end;
    Le $81 veut dire : ne pas appeler BeforeDestruction, mais appeler FreeInstance.
    Il n'existe malheureusement pas de code pour dire : appeler BeforeDestruction mais pas FreeInstance.

    Pour compléter le tout, un appel tel que :
    se traduit du coup en :
    Tandis que l'appel au destructeur hérité :
    se traduit en :
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

Discussions similaires

  1. Réponses: 6
    Dernier message: 10/10/2007, 20h11
  2. Comment l'appel à une méthode virtuelle....
    Par Blobette dans le forum C++
    Réponses: 7
    Dernier message: 07/12/2004, 13h55
  3. appel entre méthodes de meme classe
    Par frmaniako dans le forum C++
    Réponses: 8
    Dernier message: 10/09/2004, 22h55
  4. [Débutant] [JSP] Appel de méthode
    Par Crazyblinkgirl dans le forum Servlets/JSP
    Réponses: 10
    Dernier message: 10/09/2004, 11h10
  5. [Débutant] Héritage & appel de méthodes
    Par KooX dans le forum Langage
    Réponses: 4
    Dernier message: 11/05/2004, 23h37

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