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

Langage Delphi Discussion :

Récuperer la valeur retournée d'une fonction.


Sujet :

Langage Delphi

  1. #21
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Citation Envoyé par Bruno Orsier
    je pinaille surement, mais la liste créée dans la fonction sera bien libérée, c'est la 1ère liste qui sera perdue. En simplifiant au maximum,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    vList := TStringList.Create ; // référence qui sera perdue
    vList := TStringList.Create ;
    vList.Free ;
    B.
    Désolé, je ne te suis pas là !
    A quoi ça sert la double création de "vList" ?
    Si vous êtes libre, choisissez le Logiciel Libre.

  2. #22
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Juste histoire d'en rajouter une couche, vues ce que je considère comme des lacunes dans la syntaxe de Delphi (on en a déjà discuté), je suis du même avis que TicTacToe : toujours rendre "symétrique" la création/libération des objets, et ne jamais, jamais renvoyer un objet comme valeur de retour d'une fonction, ni créer d'objet à l'intérieur d'une procédure, en vue de le transmettre par variable à l'extérieur de ladite procédure.

    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
    type TMonObjet = class ... end;
     
    procedure FaireDesTrucsAMonObjet(MonObjet:TMonObjet;DesTrucs:TTrucs);
     begin
      // Pas de retour d'objet, pas de Create ni de Free dans le bloc.
      MonObjet.LesTrucs:=DesTrucs;
     end;
     
    var UnObjet:TMonObjet;
     
    begin
     UnObjet := TMonObjet.Create; // Create et...
     FaireDesTrucsAMonObjet(UnObjet,TrucMuche);
     ...
     UnObjet.Free; // ... Free dans le même bloc, "symétriques".
    end;

  3. #23
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Citation Envoyé par CapJack
    Juste histoire d'en rajouter une couche, vues ce que je considère comme des lacunes dans la syntaxe de Delphi (on en a déjà discuté), je suis du même avis que TicTacToe : toujours rendre "symétrique" la création/libération des objets, et ne jamais, jamais renvoyer un objet comme valeur de retour d'une fonction, ni créer d'objet à l'intérieur d'une procédure, en vue de le transmettre par variable à l'extérieur de ladite procédure.
    Et pourquoi c'est permis par Delphi ?
    Cette proposition de Paul Toth est bien correct :

    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
    function StringListFromFile(const FileName:string):TStringList;
    begin
     Result:=TStringList.Create;
     if FileExist(Path1+FileName) then
      Result.LoadFromFile(Path1+FileName)
     else
     if FileExist(Path2+FileName) then
      Result.LoadFromFile(Path2+FileName);
    end;
     
    var
     l1,l2:TStringList;
    begin
     l1:=StringListFromFile('file1.txt');
     l2:=StringListFromFile('file2.txt');
     ...
     l1.free;
     l2.free;
    end;
    Si vous êtes libre, choisissez le Logiciel Libre.

  4. #24
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par sjrd
    Euh ben exactement comme TicTacToe l'a écrit dans son dernier message.

    Où est le problème ?
    le problème est plus profond je pense

    il relève de la méconnaissance des pointeurs :p

    petit rappel donc...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var
     o:TObject;
    begin
     o:=TObject.Create;
    end;
    le code ci-dessus fait deux choses
    1) il alloue une zone mémoire pour un TObject
    2) il place dans la variable "o" l'adresse de cet objet en mémoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var
     o1:TObject;
     o2:TObject;
    begin
     o1:=TObject.Create;
     o2:=o1;
    end;
    le code ci-dessus fait trois choses
    1) il alloue une zone mémoire pour un TObject
    2) il place dans la variable "o1" l'adresse de cet objet en mémoire
    3) il place dans la variable "o2" l'adresse du MEME objet en mémoire

    Donc si on en revient au code proposé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    function GetObject:TObject;
    begin
     Result:=TObject.Create;
    end;
     
    var
     o:TObject;
    begin
     o:=GetObject;
     o.Free;
    end;
    le code ci-dessus est en tout point équivalent au précédent
    1) la fonction GetObject alloue une zone mémoire pour un TObject
    2) elle place dans la variable "Result" l'adresse de cet objet en mémoire
    3) le code place dans la variable "o" l'adresse du MEME objet en mémoire

    "Result" n'est pas ici l'objet lui-même mais seulement son adresse en mémoire, ce n'est donc pas "Result" qui doit être libéré (tout comme on ne libère par un INTEGER par exemple) mais bien l'objet dont l'adresse est contenue dans "Result"...or cet objet sera libéré quand on en aura plus besoin. Pour l'instant on garde son adresse dans la variable "o" et c'est lors de l'appel de "o.Free" qu'il sera libéré.

    Un pointer c'est un peu comme un indice dans un tableau, ce tableau n'est rien d'autre que la mémoire
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #25
    Teo
    Teo est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Août 2002
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 110
    Points : 111
    Points
    111
    Par défaut
    Jolie démo du fameux
    "Ce qui ce conçoit bien s'énonce clairement...."

    Jai eu qlq fois des soucis avec les "Result := Objet".
    Je crois mieux comprendre pourquoi !
    Je leurs préférais d'ailleurs des fonctions avec passages de valeurs par adresses.

    Dans le cas de cette discussion la proposition
    Citation Envoyé par TicTacToe
    Il ne faut pas perdre de vu que pModeReglement est une fonction. Si tu l'inscris 2 fois dans le code, elle sera appelée 2 fois.

    Pour libérer la liste allouée dans pModeReglement,
    Lors de l'appel il faut faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var
      MaListe: TStringList;
    begin
      MaListe := pModeReglement;
      // utilisation de MaListe...
      MaListe.Free;
    comme l'a montré Paul Toth
    est donc tres valable , si ce n'est la meilleure pour garder la logique initiale.

  6. #26
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Merci beaucoup Paul TOTH pour votre démonstration, elle est très claire et profiteras j'espère a tous.(dont moi-même bien-sûr )
    Si vous êtes libre, choisissez le Logiciel Libre.

  7. #27
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Citation Envoyé par TryExceptEnd
    Et pourquoi c'est permis par Delphi ?
    Ne mélangeons pas syntaxe du langage et bonnes habitudes de développement.

    Personnellement, tout ce qui a été développé dans ce fil m'est acquis depuis au moins quinze ans. Le problème, c'est que renvoyer un objet créé à l'intérieur d'une fonction comme valeur de cette fonction me hérisse le poil, d'un point de vue logique et théorique.

    C'est parfaitement possible, oui, mais horriblement dangereux. Reparlons-en quand vous aurez fait l'expérience des fameuse "fuites de mémoire" prétendument inexplicables...

  8. #28
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par CapJack
    Ne mélangeons pas syntaxe du langage et bonnes habitudes de développement.

    Personnellement, tout ce qui a été développé dans ce fil m'est acquis depuis au moins quinze ans. Le problème, c'est que renvoyer un objet créé à l'intérieur d'une fonction comme valeur de cette fonction me hérisse le poil, d'un point de vue logique et théorique.
    tu peux développer ?

    Citation Envoyé par CapJack
    C'est parfaitement possible, oui, mais horriblement dangereux. Reparlons-en quand vous aurez fait l'expérience des fameuse "fuites de mémoire" prétendument inexplicables...
    ça n'a pas grand chose à voir, voici un exemple de fuite de mémoire sans fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    procedure test;
    var
     t:TObject;
    begin
     t:=TObject.Create;
    end;
    ça c'est la pour la question de logique

    et un exemple d'usage de fonction sans fuite
    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
     
    unit test;
     
    interface
     
    function getInstance:TObject;
     
    implementation
     
    var
     gInstance:TObject;
     
    function getInstance:TObject;
    begin
     if gInstance=nil then gInstance:=TObject.Create;
     Result:=gInstance;
    end;
     
    initialization
     gInstance:=nil;
    finalization
     gInstance.Free;
    end.
    ce qui s'apparente à la définition d'un singleton ...ça c'est pour la théorie

    en plus je vois pleins d'autres cas ou l'usage d'une fonction est idéal, comme par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function TMyParent.AddChild:TCustomChild;
    begin
     if assigned(fOnGetChild) then 
      Result:=fOnGetChild(Self)
     else
      Result:=TDefaultChild.Create(Self);
    end;
    en fait tout est possible, il suffit de savoir ce qu'on fait
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #29
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Non, je n'ai pas envie de développer ni de polémiquer sur le sujet. Il y a déjà eu d'autres problèmes du même genre soulevés, et j'ai déjà expliqué mon point de vue sur la question plusieurs fois. Comme tu dis, "il suffit de savoir ce qu'on fait", mais l'observation de bien des codes et de bien des habitudes montre que c'est loin d'être le cas de tout le monde. Je le dis sans aucune forfanterie.

    Ton dernier exemple n'est pas convaincant car il s'agit de la création d'un composant associé à un composant parent. Dans ce cas, le composant créé est ajouté à une liste, et sera donc automatiquement détruit à la destruction du parent. On est dans un cas très particulier, dans lequel un mécanisme spécifique est en jeu.

    Quant à l'exemple précédent, l'utilisation d'une variable globale... hum hum. C'est vraiment vouloir prouver qu'on a raison par tous les moyens, y compris les plus malhonnêtes.

    Edit : Précisons : je n'ai évidemment jamais prétendu qu'il y avait bijection entre les fuites de mémoire et l'utilisation des fonctions, je dis simplement que la création d'un objet dans une fonction, objet qu'on oublie ensuite de libérer, est une erreur fréquemment commise par les débutants en Delphi, et que dans un souci de pédagogie, je propose d'éviter aux débutants des raccourcis qui ressemblent fort à des pièges qu'ils se tendent eux-même. Maintenant on a le droit de ne pas être d'accord avec ce point de vue.

  10. #30
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par CapJack
    Non, je n'ai pas envie de développer ni de polémiquer sur le sujet. Il y a déjà eu d'autres problèmes du même genre soulevés, et j'ai déjà expliqué mon point de vue sur la question plusieurs fois. Comme tu dis, "il suffit de savoir ce qu'on fait", mais l'observation de bien des codes et de bien des habitudes montre que c'est loin d'être le cas de tout le monde. Je le dis sans aucune forfanterie.
    dommage, j'ai raté tes explications, j'aurais bien aimé savoir ce qui te "hérisse le poil"

    Citation Envoyé par CapJack
    Ton dernier exemple n'est pas convaincant car il s'agit de la création d'un composant associé à un composant parent. Dans ce cas, le composant créé est ajouté à une liste, et sera donc automatiquement détruit à la destruction du parent. On est dans un cas très particulier, dans lequel un mécanisme spécifique est en jeu.

    Quant à l'exemple précédent, l'utilisation d'une variable globale... hum hum. C'est vraiment vouloir prouver qu'on a raison par tous les moyens, y compris les plus malhonnêtes.
    serais-tu de ceux qui considèrent qu'il faut programmer sous Delphi comme si les variables globales et les fonctions n'existaient pas pour ne faire que du 100% objet ?

    Note que la variable de mon exemple n'est pas réellement "globale" puisqu'elle est locale à l'unité.

    Citation Envoyé par CapJack
    Edit : Précisons : je n'ai évidemment jamais prétendu qu'il y avait bijection entre les fuites de mémoire et l'utilisation des fonctions, je dis simplement que la création d'un objet dans une fonction, objet qu'on oublie ensuite de libérer, est une erreur fréquemment commise par les débutants en Delphi, et que dans un souci de pédagogie, je propose d'éviter aux débutants des raccourcis qui ressemblent fort à des pièges qu'ils se tendent eux-même. Maintenant on a le droit de ne pas être d'accord avec ce point de vue.
    Pour moi, la pédagogie n'a jamais consisté à prendre les gens pour des cons en leur faisant croire qu'il ne faut pas faire des choses dont on pense qu'ils ne les maitriseront pas...mais bien d'énoncer clairement ce dont il retourne

    Tu trouves mes exemples non pertinents ou barbares, mais le débutant ne fera pas les mêmes distinctions si on lui bourre le crane en disant qu'une fonction ne doit pas retourner un objet qu'elle instancie car c'est simplement faux.

    Et je ne suis pas du genre à vouloir embrouiller les gens...j'ai d'ailleurs regardé de travers l'arrivée des tableaux dynamique qui noircissent des pages et des pages de forums sur pourquoi mon code déconne...tout comme la compatibilité chaine "longue" et PChar

    A bas l'obscurantisme !
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #31
    Membre du Club Avatar de mamou30
    Inscrit en
    Janvier 2007
    Messages
    118
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 118
    Points : 67
    Points
    67
    Par défaut
    Salut a tous
    Voici une fonction qui peut t'aider
    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
     
    function TForm1.pModeReglement:TStringList;
    var pModeReglement1:TStringList;
    begin
    pModeReglement1:=TStringList.Create;
      try
        with pModeReglement1 do begin
         Add(ComboBox1.Text);
         Add(edit1.text);
     
        end;
        result:=pModeReglement1;
         showmessage( result.Text)
        finally
     
    pModeReglement1.free;
    end;
    le showmessage( result.Text) c'est juste pour voir le resultat

  12. #32
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Citation Envoyé par Paul TOTH
    Tu trouves mes exemples non pertinents ou barbares, mais le débutant ne fera pas les mêmes distinctions si on lui bourre le crane en disant qu'une fonction ne doit pas retourner un objet qu'elle instancie car c'est simplement faux.
    Je n'affirme pas qu'elle ne doit pas, mais qu'il vaut mieux éviter tant qu'on ne maîtrise pas la programmation objet... je suis d'accord avec toi sur le plan de la programmation, mais :

    Je suis convaincu que dans tout apprentissage il faut y aller petit à petit, et que ce n'est pas "prendre les gens pour des cons" que d'essayer de les faire progresser étape par étape : chaque chose en son temps. Prendre les gens pour des cons, ce serait selon moi aider de façon cyniquement incompréhensible. Ce n'est pas pour rien si dans les programmes officiels de l'école, il y a une progression à respecter strictement. Mais c'est un vaste débat...

    Pour en revenir à notre exemple : faire renvoyer par une fonction un objet qu'elle instancie, et gérer correctement en retour la libération de cet objet, sans parler de la gestion des exceptions, n'est - selon moi, mais je me trompe certainement - pas une compétence de débutant, c'est tout. Entre autres, à cause du déréférencement automatique des pointeurs, par exemple.


    Edit : mamou30, tu illustres parfaitement mon propos : tu libères systématiquement l'objet qui va être renvoyé par la fonction, ce qui fait que le résultat renvoyé ne sera jamais valide !

  13. #33
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par CapJack
    (zap)
    Pour en revenir à notre exemple : faire renvoyer par une fonction un objet qu'elle instancie, et gérer correctement en retour la libération de cet objet, sans parler de la gestion des exceptions, n'est - selon moi, mais je me trompe certainement - pas une compétence de débutant, c'est tout. Entre autres, à cause du déréférencement automatique des pointeurs, par exemple.
    (zap)
    je suis tombé sur un autre post de toi sur ce que tu qualifies de problème : le "déréférencement automatique des pointeurs".

    Pour avoir longtemps travaillé en Turbo Pascal avec les "OBJECT" qui sont les objets statiques que tu aurais aimé avoir, je peux te dire que j'approuve totalement le choix qui a été fait par Borland de faire des classes Delphi de pointeurs automatiquement

    99% de mes sources Turbo Pascal de l'époque utilisaient des ^Object avec des MonObject^.Propriété...c'est presque aussi chiant que le "->" des autres langages.

    Avoir rendu le "^" optionnel sur les pointeurs et illégal sur les "CLASS" est une bonne chose à mes yeux

    Alors c'est sur que quand tu viens d'un autre langage ou tout est objet, tu as tendance à vouloir faire du 100% objet en Pascal, et je pense personnellement que c'est une erreur !

    Si tu veux du 100% objet, tu as des langages qui l'impose, autant les utiliser. Si tu le fais en Pascal, grand bien t'en face, mais prétendre que c'est comme ça qui faut programmer en Pascal est une hérésie à mes yeux

    La simple notion d'Unité qui est, me semble-t-il propre à ce langage, permet de gérer automatiquement les namespaces et des variables "globales mais privées" comme mon gInstance de toute à l'heure. Ne pas utiliser ces possibilités du langage c'est se priver d'outils bien pratiques. Tout comme je préfère de loin une unité SysUtils ou DateUtils avec toutes ces fonctions, qu'une classe TDate avec des fonctions de classe qui ne fait qu'ajouter une couche là ou l'unité répond parfaitement au besoin.

    Enfin bon, ce débat date pas d'hier, et ne se terminera pas demain
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #34
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Citation Envoyé par Paul TOTH
    je suis tombé sur un autre post de toi sur ce que tu qualifies de problème : le "déréférencement automatique des pointeurs".
    Euh... Ce n'est pas moi qui ai inventé les termes de déréférencer ou déréférencement, mais Borland itself dans la seule doc version papier que j'ai, celle de Delphi 3. D'ailleurs cette doc utilise systématiquement le terme de référence d'objet, pour parler du contenu d'une variable de type classe.


    Citation Envoyé par Paul TOTH
    Pour avoir longtemps travaillé en Turbo Pascal avec les "OBJECT" qui sont les objets statiques que tu aurais aimé avoir, je peux te dire que j'approuve totalement le choix qui a été fait par Borland de faire des classes Delphi de pointeurs automatiquement

    99% de mes sources Turbo Pascal de l'époque utilisaient des ^Object avec des MonObject^.Propriété...c'est presque aussi chiant que le "->" des autres langages.

    Avoir rendu le "^" optionnel sur les pointeurs et illégal sur les "CLASS" est une bonne chose à mes yeux
    Ben justement ! C'est bien parce que nous avons tous les deux, à une époque donnée, connu cette syntaxe, que nous maîtrisons parfaitement le sujet, et que nous savons ce que recouvre la syntaxe Objet.Truc. Encore une fois, je suis désolé d'insister lourdement, mais c'est loin d'être acquis pour quelqu'un qui commence à travailler en Delphi. C'est tout ce que j'ai dit : d'ailleurs le fil auquel tu fais référence, si mes souvenirs sont bons, avait été initié par quelqu'un qui avait récupéré un vieux code source manifestement de l'époque pré-Delphi (ça fait un peu archéologue... ), nécessitant une adaptation.

    Citation Envoyé par Paul TOTH
    Alors c'est sur que quand tu viens d'un autre langage ou tout est objet, tu as tendance à vouloir faire du 100% objet en Pascal, et je pense
    personnellement que c'est une erreur !

    Si tu veux du 100% objet, tu as des langages qui l'impose, autant les utiliser. Si tu le fais en Pascal, grand bien t'en face, mais prétendre que c'est comme ça qui faut programmer en Pascal est une hérésie à mes yeux
    Euh... je n'ai rien affirmé de tout ça. J'ai juste dit qu'il me semblait dangereux pour quelqu'un qui débute, de faire renvoyer par une fonction un objet que la fonction instancie, j'ai un peu précisé pourquoi, et c'est tout !

    Citation Envoyé par Paul TOTH
    La simple notion d'Unité qui est, me semble-t-il propre à ce langage, permet de gérer automatiquement les namespaces et des variables "globales mais privées" comme mon gInstance de toute à l'heure. Ne pas utiliser ces possibilités du langage c'est se priver d'outils bien pratiques. Tout comme je préfère de loin une unité SysUtils ou DateUtils avec toutes ces fonctions, qu'une classe TDate avec des fonctions de classe qui ne fait qu'ajouter une couche là ou l'unité répond parfaitement au besoin.
    Ben, euh... oui, oui...

    Il y avait un smiley pour exprimer l'ironie du terme "mauvaise foi", hein ?

  15. #35
    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 445
    Points
    28 445
    Par défaut
    oups, désolé, j'y suis aller un peu fort et j'ai présumé de tes idées

    et les débutants doivent avoir décroché de notre débat

    bonne soirée
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  16. #36
    Membre éprouvé
    Avatar de CapJack
    Homme Profil pro
    Prof, développeur amateur vaguement éclairé...
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Prof, développeur amateur vaguement éclairé...
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 988
    Points
    988
    Par défaut
    Ya pas d'mal...

    En fait, c'est juste une question de style de programmation. Je me suis peut-être mal exprimé au début, en voulant aller trop vite. Je vais conclure en essayant de clarifier au maximum mon idée.

    Une règle d'Or à laquelle je me soumets moi-même, depuis bientôt un quart de siècle que je programme en Pascal, et bien qu'elle ne soit en aucune manière une obligation liée à la syntaxe du langage, est la suivante :

    toujours laisser l'affectation d'un pointeur à la charge de la procedure appelante..

    En d'autres termes, j'évite ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure Appelée(var P:PMonTruc);
     begin
      New(p);
      // ... remplir p^ avec des machins
     end;
     
    procedure Appelante;
     var p:PMonTruc;
     begin
      Appelée(p);
      Dispose(p);
     end;
    Je préfère celà :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure Appelée(const P:PMonTruc);
     begin
      // ... remplir p^ avec des machins
     end;
     
    procedure Appelante;
     var p:PMonTruc;
     begin
      New(p);
      Appelée(p);
      Dispose(p);
     end;
    Je trouve en effet plus élégant de coder l'affectation et la libération dans le même bloc de code, plutôt que l'affectation à un endroit, et la libération à un autre. En plus, l'expérience personnelle m'a prouvé que de s'imposer ce genre de contrainte rend le code plus robuste et plus facile à maintenir et à comprendre sur le long terme. On évite plus facilement l'oubli de libérer la mémoire utilisée, car le code est visuellement symétrique. En tout cas, pour moi, c'est presque une nécessité intellectuelle.

    Ensuite, qu'on renvoie le pointeur affecté dans un paramètre var ou dans le Result d'une fonction revient fondamentalement au même du point de vue de cette règle que je m'impose : c'est toujours le probèlme de l'affectation à un endroit, libération à un autre.

    Enfin, s'agissant des objets, on ne le dira jamais assez, les variables objet ne sont en Delphi que des références, donc des pointeurs. Donc, j'applique la règle précédente, avec la contrainte renforcée qu'en plus d'affecter/libérer un pointeur, on instancie/libère un objet.

    En espérant avoir cette fois été plus clair.

  17. #37
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par CapJack
    Ya pas d'mal...
    tant mieux

    Citation Envoyé par CapJack
    En espérant avoir cette fois été plus clair.
    oui, je comprend bien la démarche. Mais elle va à l'encontre d'une autre règle que j'affectionne personnellement réduire le code au minimum, ce qui permet de le mieux comprendre.

    Ainsi, une fonction qui attend un paramètre qu'on va devoir instancier à chaque fois qu'on l'appelle, va m'obliger à une redondance de code qui me hérisse le poil sur le coup Quitte à faire deux procédures

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // exemple bidon :D
    procedure LireFichier(AList:TStrings; const AFileName:string):
    begin
     AList.LoadFormFile(AFileName);
    end;
     
    function ListeFichier(cosnt AFileName:string):TStrings;
    begin
     Result:=TStringList.Create;
     LireFichier(Result,AFileName);
    end;
    du coup j'ai le meilleur des deux mondes, et j'évite une ligne par procédure (le create du TStringList )

    maintenant, en effet tout cela est sujet à fuite de mémoire...C'est pourquoi j'ai pris la sale habitude d'utiliser des STRING quand c'est possible

    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
     
    // attention, je parle ici par exemple du traitement d'un fichier binaire
    // on d'un flux IP
    // pas question de faire ce genre de gymnastique dans un contexte normal :)
     
    function GetData:string;
    var
     MaStructure:^TMaStructure;
    begin
     SetLength(Result,SizeOf(TMaStructure));
     MaStructure:=@Result[1];
     MaStructure.Field1=...
    end;
     
    procedure ProcessData(const Str:string);
    var
     MaStructure:^TMaStructure;
    begin
     assert(Lengh(Str)=SizeOf(TMaStructure));
     MaStructure:=@Str[1];
     if MaStructure.Field1=...
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  18. #38
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    D'aprés ce que j'ai compris, j'ai deux solutions a mon probleme que je résume comme suit :
    - la 1ere utilise une fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure Quelconque;
    var vList:TStringList;
    begin
     vList:=FModeReglement;
     vList.Free;//Liberation de l'objet
    end;
    
    function FModeReglement:TStringList;
    begin
     Result:=TStringList.Create;//Creation de l'objet
     Result.Add('Fonction');
     Result.Add('Text');
    end;
    - la 2eme utilise une procedure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure Quelconque;
    var vList:TStringList;
    begin
     vList:=TStringList.Create;//Creation de l'objet
     PModeReglement(vList);
     vList.Free;//Liberation de l'objet
    end;
    
    procedure PModeReglement(sList:TStringList);
    begin
     sList.Add('Procedure');
     sList.Add('Test');
    end;
    Ai-je bien résumé le pourquoi du comment de ce thread ?
    Si vous êtes libre, choisissez le Logiciel Libre.

  19. #39
    Membre expert
    Avatar de TicTacToe
    Inscrit en
    Septembre 2005
    Messages
    1 940
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 940
    Points : 3 575
    Points
    3 575
    Par défaut
    Citation Envoyé par TryExceptEnd
    D'aprés ce que j'ai compris, j'ai deux solutions a mon probleme que je résume comme suit :
    ...
    Ai-je bien résumé le pourquoi du comment de ce thread ?

    Meme nombres de lignes, mais 2 méthodes différentes
    --> Yapluka

    Et n'oublie pas le 'résolu' si c'est bon pour toi
    Section Delphi
    La mine d'or: La FAQ, les Sources

    Un développement compliqué paraitra simple pour l'utilisateur, frustrant non ?
    Notre revanche ? l'inverse est aussi vrai ;-)

  20. #40
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par TicTacToe

    Meme nombres de lignes, mais 2 méthodes différentes
    --> Yapluka

    Et n'oublie pas le 'résolu' si c'est bon pour toi
    même nombre de lignes quand on ne fait qu'un appel à la fonction...mais dans ce cas je ne vois pas l'intérêt de faire une fonction, quelque soit la méthode

    encore que s'il y a du code d'initialisation supplémentaire, ça peut être intéressant pour rendre le code plus lisible

    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
     
    procedure demo;
    var
     font:TFont;
    begin
     font:=CreateFont('Terminal',12);
     ...
     font.Free;
    end;
     
    function CreateFont(const FontName:string; Size:integer):TFont;
    begin
     Result:=TFont.Create;
     Result.FontName:=FontName;
     Result.Size:=Size;
    end;
    on peut aussi déclarer ceci...mais bon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    type
     TMyFont=class(TFont)
     public
      constructor Create(const FontName:string; Size:integer); reintroduce;
     end;
    ...
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. Réponses: 8
    Dernier message: 05/04/2011, 08h06
  2. Réponses: 2
    Dernier message: 11/04/2008, 22h58
  3. Réponses: 4
    Dernier message: 07/04/2007, 20h02
  4. valeur retournée par une fonction
    Par Biosox dans le forum C
    Réponses: 13
    Dernier message: 19/01/2007, 23h17
  5. valeur retournée d'une fonction
    Par jokos2000 dans le forum Oracle
    Réponses: 8
    Dernier message: 29/06/2005, 12h21

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