Forum Programmation.c++ Adresse d'un objet?

Posté par  (site web personnel) .
Étiquettes : aucune
0
28
juin
2006
Bonjour!

J'ai le code suivant:

DString Experiment::FullShotPath(DString &relativepath);

(et "relativepath" est modifié dans la fonction) puis

void *Experiment::GetDataptr(const DString &name, DataType dType, DataAccess dAccess)
{
//First get the full data name
DString FileName;
size_t iLPos = name.RFind('\\');
[...]
FileName = FullShotPath(name.Left(iLPos));

Lorsque je compile, j'ai le message

Experiment.cpp: In member function `void* Experiment::GetDataptr(const DString&, DataType, DataAccess)':
Experiment.cpp:277: error: no matching function for call to `Experiment::FullShotPath(DString)'
Experiment.cpp:148: note: candidates are: DString Experiment::FullShotPath(DString&)


Et la, je bloque: j'ai bien essayé de faire mon appel avec "&(name.Left(iLPos))", ça ne marche pas, et je me rend compte que je ne comprend pas la syntaxe "FullShotPath(DString &relativepath)" (pour passer la valeur par addresse, cela devrait etre "DString *relativepath", non?)

Si quelqu'un a des idees...

Mathias
  • # const?

    Posté par  . Évalué à 1.

    Est-ce que par hasard ta mathode Left(...) ne renverrai pas un const DString ?
    Si c'est le cas... normal...
    Si ça renvoit un DString* encore pire...
    Bref je pense qu'il faut que tu adapte ta methode au bon type de paramètres.
    Si c'est pas ça, donne nous un copie complète de ta classe pour qu'on pointe le problème du doigt...
    • [^] # Re: const?

      Posté par  (site web personnel) . Évalué à 2.

      Bingo!

      En effet, la méthode Left() renvoie un const...

      Merci beaucoup!

      Pour répondre à tous ceux qui s'interrogent sur ma santé metale, non je ne suis pas l'auteur de ce code ! je fais simplement le portage vers Unix d'un code ecrit sous Windows, compilé avec VC++ par quelqu'un dont c'est le premier essais en C++... Que du bonheur!

      (en plus, il utilise plein de constructions que mes connaissances limitées en C++ ne parviennent pas a expliquer, plein de choses specifiques a Windows, il re-invente la roue a longueur de journees, ... Et il est persuade que son code est pur C++ et que c'est Unix qui est bizard a ne pas vouloir digerer son code (plein de bugs au demeurrant)).

      Et tout les cas, merci beaucoup pour vos réponses !

      Mathias
      • [^] # Re: const?

        Posté par  . Évalué à 2.

        Content d'avoir pu t'aider. Ce que d'autres ont posté plus bas est vrai aussi, car certains compilos n'aiment pas que l'on passe un paramètre temporaire non 'const' (ex: DString ) en à une fonction qui accepte une référence (DString&).
        Une bonne pratique est de doubler ses fonctions type get(), l'une qui renvoit un const et l'autre un modifiable (c'est ce que fait la stl à tour de bras pour les méthodes begin() et end() ).
        Et ainsi la bonne méthode sera employé si jamais tu la passe à une fonction qui doit modifier l'objet en question, et le compilo pourra rendre certaines méthodes inline automatiquement lorsque l'optimisation est activée.
        Ensuite si ta methode appelée ne modifie pas l'objet, essaye toujours de mettre le mot clef 'const' en paramètre. ça evitera souvent des problèmes.
        • [^] # Re: const?

          Posté par  (site web personnel) . Évalué à 2.

          A tout hasard.
          Matthias (OP)> En effet, la méthode Left() renvoie un const...

          J'ai l'impression en lisant cela que tu t'es contenté de lever le const du type de retour et que cela passe maintenant. Ce qui me parait surprenant. Quelle version de GCC utilises-tu ?

          NB: même si cela passe avec un ancienne version de GCC (ou tout autre vieux compilo VC6, SunWSPro 5.4, ...) il ne faut pas s'attendre à ce que cela continue ainsi -- GCC a été patché, VC a dû l'être aussi. Comme je l'ai déjà signalé il n'y a que 3 corrections valables -- et en plus compatibles avec les vieux compilos. Retirer le const n'en est pas une.
          -> DString Experiment::FullShotPath(DString const&relativepath) ; si FullShotPath n'altère pas l'objet reçu en paramètre.
          -> DString Experiment::FullShotPath(DString relativepath) ; si FullShotPath n'altère pas l'objet reçu en paramètre et que l'on est prêts à payer une copie.
          -> Temporaire nommé intermédiaire

          Dit autrement, retirer le const ne servira que sur les environnements sur lesquels on n'a pas réalisé de monté de version des compilos depuis pratiquement 8 ans.


          Bench> certains compilos n'aiment pas que l'on passe un paramètre temporaire non 'const' (ex: DString ) en à une fonction qui accepte une référence (DString&)

          Deux précisions:
          - ce n'est pas certains compilos, mais les compilos à jour sur ce point de la norme. Ceux qui ne le sont pas encore le seront très probablement dans le futur,
          - que le paramètre temporaire soit const ou pas ne change rien. Une référence ne peut pas être attachée à un temporaire.


          Bench> Une bonne pratique est de doubler ses fonctions type get(), l'une qui renvoit un const et l'autre un modifiable (c'est ce que fait la stl à tour de bras pour les méthodes begin() et end() )

          Cela ne s'utilise pas dans le même contexte. Si getLeft() renvoie une valeur créée à la volée et ne modifie pas l'objet sur lequel elle est appliqué, alors la fonction doit être const, et renvoyer une copie. Que la copie renvoyée soit const empêche, aujourd'hui, d'appeler des fonctions (membre) non const sur l'objet renvoyé.
          Les deux versions de begin() et end() des conteneurs de la SL permettent d'obtenir des itérateurs vers des données modifiables, sauf pour les conteneurs non modifiables qui ne permettent d'obtenir que des itérateurs vers des données itérables non modifiables.
          • [^] # Re: const?

            Posté par  . Évalué à 1.

            Tu as certainement plus que raison, je ne connais pas aussi bien la norme que toi. Le C++ c'est pour moi un apprentissage permanent forgé par l'expérience.
            Cependant, qu'une référence constante ne puisse pas être attachée à un temporaire, je trouve ça idiot. Une référence, c'est pour moi un moyen de ne pas faire passer un pointeur comme en C et d'éviter un tas d'assert not null, éviter l'utilisation d'une variable et ainsi d'obtenir un code plus conçis et donc lisible . Si l'objet renvoyé par copie temporaire est passé en référence constante, il me semble logique qu'une variable soit implicitement utilisée par le compilo et ainsi étendre sa durée de vie à l'appel de fonction en retour.

            exemple :

            void test(const int& i){
            ....
            }

            int main(int argc, char* argv[]){
            test(3);
            }

            ça marche avec mon gcc3.4. Donc gcc3.4 n'est pas à jour sur ce point de la norme?
            • [^] # Re: const?

              Posté par  (site web personnel) . Évalué à 1.

              Au temps pour moi.
              Je voulais bien évidemment parler des "références non-const qui ne peuvent être attachées à des temporaires (non nommés)".

              Tout ce que demande la référence const, c'est une convertion implicite entre le type de l'expression (produisant un éventuel temporaire) et le type de la référence-const.

              Soit, ton GCC se comporte normalement.
          • [^] # Re: const?

            Posté par  (site web personnel) . Évalué à 2.

            J'ai l'impression en lisant cela que tu t'es contenté de lever le const du type de retour et que cela passe maintenant

            Ouh, loin de moi cette idée!
            J'ai en fait modifie FullShotPath() pour que le parametre soit tout d'abord copié avant de travailler sur la copie (qui est utilisé comme une variable temporaire).

            Donc maintenant, le parametre est "const", et ce qui devait etre fait reste caché dans la fonction FullShotPath(). (en plus, cela me choquait de modifier le contenu du chemin relatif passé en parametre: cela veux dire que apres un appel a cette fonction, ce chemin est corrompu et inutilisable pour la suite, ce qui est vraiment idiot).

            Mathias
            PS: en tout les cas, merci pour les explications !
  • # temporaires non nommés

    Posté par  (site web personnel) . Évalué à 1.

    Ta fonction qui prend un DString& ne peut pas accepter de paramètre non nommé.
    Si elle ne modifie pas ce qu'elle reçoit => "Dstring const&"
    Si elle modifie ce qu'elle reçoit => nomme ton temporaire.

    Vu que tu programmes en C++, tu sais que tu as tout ce qu'il faut dans boost.file_system pour manipuler des chemins ? (Cela repose sur la classe de chaînes standard std::string)
  • # La methode n'est pas déclarée

    Posté par  (site web personnel) . Évalué à 1.

    FullShotPath(DString &relativepath) veut dire que la valeur est passée par référence. Ca veut dire que tu fais comme si tu la passait par valeur alors qu'en réalité c'est l'adresse qui est passée. Ce qui fait que ce n'est pas une copie.

    Mais pour que cela marche il faut pouvoir prendre l'adresse de ce que tu passe en argument. Or ton argument est une valeur temporaire résultat d'un fontion. Tu dois l'affecter a une variable pour pouvoir l'utiliser comme référence.


    DString donneMoiUnNom = name.Left(iLPos);
    FileName = FullShotPath(donneMoiUnNom);
    • [^] # Re: La methode n'est pas déclarée

      Posté par  . Évalué à 3.

      Non.

      Un nom de variable n'est qu'une référence à un objet en mémoire, au moment de la compilation. Le retour d'une fonction génère un objet en mémoire à une adresse fixe, et qui peut tout à fait être utilisé comme tel.

      Par contre, il se peut que le compilateur (cela dépend des versions, en fait) se plaigne car l'objet, temporaire, n'est pas forcément modifiable. Sémantiquement, cela reste incorrect car le prototype de la fonction imbriquée, lui, est formel.

      Avec g++ 3.3, j'obtiens :


      $ g++ refdef.c++ -o refdef
      refdef.c++: In function `int main()':
      refdef.c++:35: error: invalid initialization of non-const reference of type 'A&' from a temporary of type 'A'
      refdef.c++:22: error: in passing argument 1 of `void First(A&)'

      $ g++ -v
      Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.3.3/specs
      Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
      --infodir=/usr/share/info --enable-shared --enable-threads=posix
      --disable-checking --disable-libunwind-exceptions --with-system-zlib
      --enable-__cxa_atexit --host=i386-redhat-linux
      Thread model: posix
      gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7)


      Avec


      /*
      ...
      */
      #include

      class A { public: int x; };

      void First (A & a) { a.x == 0; }

      A Second (void) { return A(); }

      int main (void)
      {
      First ( Second () );
      return 0;
      }
      • [^] # Re: La methode n'est pas déclarée

        Posté par  (site web personnel) . Évalué à 0.

        La norme ne permet pas de placer des références non const sur des temporaires non nommés. Peu importe ce que fait la fonction First dans son corps. Seule la signature compte. D'où que si la fonction ne modifie pas la variable, alors il vaut mieux prendre une référence constante (abus de langage -> "référence sur objet non modifiable" est plus "correct"), ou une copie (ce qui fait perdre l'aspect [in,out] de la référence)

        Ce sont les vieux compilos qui acceptaient cela.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.