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 :

Impossibilité de paramètre Var


Sujet :

Delphi

  1. #1
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut Impossibilité de paramètre Var
    Bonjour,
    En développant en POO avec Delphi, du moins en essayant, je suis arrivé au message d'erreur suivant :
    "un objet constante ne peut être passé comme paramètre var"
    Voici le code (d'exemple)
    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
      Monstre = class
      end;
     
      Piece = class
      private
        _m : Monstre;
      public
        property m : Monstre read _m write _m;
      end;
     
      Heros = class
      public
        procedure combattre(var M : Monstre);
      end;
    Et voici, un extrait de son utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    var
      her : Heros;
      p : Piece;
    begin
    //instanciation puis
    her.combattre(p.m);
    //puis libération
    C'est sur her.combattre(p.m) (où p est une pièce, et m la property) que le compilateur bloque avec le message d'erreur "un objet constante ne peut être passé comme paramètre var"...

    Pourquoi ? Passer par une property empêche donc de fournir une variable par adresse ?

    Par la suite, j'ai enlevé le paramètre en tant que var (passage par adresse), et là surprise, en enlevant var, l'objet a quand même été passé par adresse !
    Bref, il y a anguille sous roche ! Auriez-vous une explication ?

    Merci d'avance, Jacques

  2. #2
    Membre expert
    Avatar de Eric Sigoillot
    Inscrit en
    Mars 2002
    Messages
    1 212
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 212
    Points : 3 369
    Points
    3 369
    Par défaut
    Bonjour,

    Une propriété ne peut pas être considérée comme une variable mais plus comme un "pointeur" vers un attribut d'un objet.

    @++
    Règles du forum
    F.A.Q Pascal

    Pour me joindre (aucune question technique, merci)

  3. #3
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    Difficile à formuler, mais tout à fait normal.

    Supposons que notre procedure utilise un paramètre Var
    La procédure va modifier le contenu pointé par l'adresse passée en paramètre.

    Il est impossible de passer la property d'un objet en tant que Var, car la procédure ne connaissant pas l'objet ne pourra pas appeler la procedure Write de la property.

    Si la property est elle-même un objet, inutile de la passer en var : ce qui est cloné est l'adresse de l'objet, mais cette adresse pointera évidemment sur les mêmes données que l'objet initial.

    Donc, en règle générale, on ne passe pas un objet en var lorsqu'on désire seulement manipuler les données. On utilisera le var seulement lorsqu'on veut retourner une instance différente de l'objet.

    Désolé, j'ai pas été très inspiré sur la formulation, c'est peut-être pas très clair.

    modifiables ce qui n'.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  4. #4
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Merci.
    On n'a donc pas besoin de var... s'il s'agit d'un "pointeur"... [un pointeur bien particulier quand même]

    Est-ce que le code proposé vous paraît "valide" ou seriez-vous amené à faire autrement pour combattre ce monstre (qui est contenu dans une pièce) ?
    A+, Merci encore, Jacques

  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
    Citation Envoyé par doustij
    Merci.
    On n'a donc pas besoin de var... s'il s'agit d'un "pointeur"... [un pointeur bien particulier quand même]

    Est-ce que le code proposé vous paraît "valide" ou seriez-vous amené à faire autrement pour combattre ce monstre (qui est contenu dans une pièce) ?
    A+, Merci encore, Jacques
    Ben c'est-à-dire que je ne vois pas pourquoi tu utilises un paramètre var justement. Sais-tu qu'un objet (instanciation d'une classe) est lui un pointeur réel ? Et que donc la modification des propriétés du paramètre M va changer les mêmes propriétés de p.m (puisque c'est la même zone mémoire).
    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 à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Tentative de résumé :

    Une procedure avec un paramètre var est capable de modifier le contenu pointé. Il s'agit d'un passage par adresse. Cela sert notamment pour modifier des réels, etc.

    Un objet (une instance de classe) est un pointeur. Le passage d'un objet comme paramètre se fait automatiquement par adresse.

    Le monstre est un objet; Il n'a donc pas besoin d'être passé en var (il l'est automatiquement).
    Les deux procedures suivantes sont donc équivalentes :
    procedure Heros.Combattre(M : Monstre)
    procedure Heros.Combattre(var M:Monstre)
    (ces deux procédures sont d'ailleurs acceptées par Delphi)

    Quand je passe une property d'un objet en paramètre, celle-ci est également transmise par adresse.
    Si je voulais faire un passage par valeur (uniquement) d'un objet ou d'une property, il faudrait d'abord que je clone cet objet (ou cette property) pour avoir une instance différente.

    Est-ce juste ? Y a-t-il des erreurs ?
    Merci pour vos réponses Jacques

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    624
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 624
    Points : 754
    Points
    754
    Par défaut
    Il ya bien passage par valeur mais dans le cas de la transmission d'un objet la valeur est une adresse.
    Si l'on ne souhaite pas modifier l'objet pointé il est préférable d'utiliser le mot clé const.

  8. #8
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Donc, si la property désignait un entier, le passage se ferait par valeur, et c'est parce que c'est un objet que le passage se fait par adresse ?

  9. #9
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    Quand je passe une property d'un objet en paramètre, celle-ci est également transmise par adresse.
    Si je voulais faire un passage par valeur (uniquement) d'un objet ou d'une property, il faudrait d'abord que je clone cet objet (ou cette property) pour avoir une instance différente.
    Pour le texte qui précède ce passage, les conclusions étaient OK.

    Une property d'un objet ne peut se transmettre que par valeur à une procédure, parceque qu'une property n'a pas d'adresse. Si on voulait passer en var, la procédure appelée ne saurait pas comment modifier la variable : elle ne connait pas la procédure "Write" qui permet de modifier la property.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  10. #10
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Une property est donc juste un pointeur ... Elle contient donc une adresse.
    Mais alors comment le compilateur emballe-t-il le bébé de telle sorte qu'il utilise ce que l'on indique en read et en write ? (normalement deux fonctions...). Que stocke-t-il, comment ?
    A priori, il ne stocke pas :
    adresse de la variable pointée, adresse de la fonction read, adresse de la fonction write,
    car, si tel était le cas, le passage en var deviendrait possible ?

    Pourquoi cette pauvre procédure ne connaît-elle pas la fonction write ?
    elle ne connait pas la procédure "Write" qui permet de modifier la property.
    Et connaît-elle d'ailleurs la fonction read ? (si l'on indique une fonction dans read ...). Il me semblerait logique que la procédure ne connaisse pas plus la fonction read que la fonction write, mais qu'elle puisse juste lire le contenu de la variable ( et donc le passage est obligatoirement par valeur - en fait par adresse (mais sans var) ).

    C'est mieux ?

  11. #11
    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
    En fait, m'en voulez pas mais... Vous êtes à côté de la plaque

    Un propriété... Ca n'existe pas Non, je ne me moque pas de vous : les propriétés, c'est du néant.

    Au moment de la compilation, tout accès écriture à une propriété, donc du type :
    est transformé, soit en l'accès au champ privé correspondant :
    soit en un appel au setter correspondant :
    Dans tous les autres cas, il s'agit d'une lecture, par exemple :
    est transformé, soit en :
    soit en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UneVar := Object.GetProp;
    Donc, une fois compilé, la propriété n'a plus aucune existence. C'est pourquoi il est impossible de la passer en paramètre var, ce qui réclame un espace mémoire bien réel, or la propriété n'en a pas.

    CQFD
    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.

  12. #12
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    En fait, m'en voulez pas mais... Vous êtes à côté de la plaque


    Après avoir imprimé, relu, crayonné le message précédent, les choses deviennent plus clair... mais c'est encore un peu le brouillard...

    La property n'existe plus ! C'est fabuleux.
    Bon, je me dis alors que le compilateur bloque sur
    her.combattre(p.m)
    car m est une propriété de la pièce

    qu'à cela ne tienne... je fais le travail du compilateur
    et hop
    her.combattre(p.getm())
    Or, là j'ai toujours l'erreur "un objet constante ... comme paramètre var".
    Par contre, si
    her.combattre(p._m)
    (en rendant la propriété publique - quelle horreur !)
    il n'y a pas d'erreur de compilation.

    Pourquoi le compilateur me refuse-t-il
    her.combattre(p.getm()) ?
    (pourtant, là la property a disparu)
    (et il bloque toujours sur le "var" alors que p.getm() renvoie bien l'adresse du monstre... - du point de vue logique p.getm() marche bien comme un var que l'on mette var ou non (j'ai retesté))

    Je crois que je suis toujours à côté de la plaque
    mais p._m est une "vraie" variable qui possède une adresse propre alors
    que p.getm() donne au compilateur l'adresse d'une fonction... (et donc d'une constante - tiens, une fonction c'est une constante ?)

    Mieux ou ?

  13. #13
    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
    Bon, en clair, lorsqu'un paramètre est var, tu ne peux lui passer qu'une variable. Que ce soit une variable locale, une variable paramètre (non-const) de la procédure appelante, une variable champ d'une classe ou d'un record.
    Mais getm c'est une fonction, pas une variable. m c'est une propriété, pas une variable. _m c'est une variable champ de classe, donc c'est bon.
    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.

  14. #14
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Merci... C'est super clair maintenant !

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/08/2010, 17h17
  2. Réponses: 3
    Dernier message: 04/01/2010, 19h32
  3. Réponses: 2
    Dernier message: 10/09/2007, 08h58
  4. Réponses: 10
    Dernier message: 04/07/2006, 20h57
  5. Réponses: 4
    Dernier message: 20/05/2006, 21h41

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