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 C++ Discussion :

Où placer mes fonctions inline (.h ou .cpp) ?


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Où placer mes fonctions inline (.h ou .cpp) ?
    En théorie (d'après ce que j'ai lu sur Internet) que je fasse
    Code myfile.h : 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
    #ifndef MYFILE_H
    #define MYFILE_H
     
    #include <QObject>
     
    class MyFile : public QObject
    {
        Q_OBJECT
     
    public:
        MyFile();
     
        void setName(const QString & name) { this->name = name; }
     
    private:
        QString name;
    };
     
    #endif
    Code myfile.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "myfile.h"
     
    MyFile::MyFile()
    {
    }

    ou bien
    Code myfile.h : 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
    #ifndef MYFILE_H
    #define MYFILE_H
     
    #include <QObject>
     
    class MyFile : public QObject
    {
        Q_OBJECT
     
    public:
        MyFile();
     
        void setName(const QString & name);
     
    private:
        QString name;
    };
     
    #endif
    Code myfile.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include "myfile.h"
     
    MyFile::MyFile()
    {
    }
     
    inline void MyFile::setName(const QString & name)
    {
        this->name = name;
    }

    ...cela devrait faire la même chose.

    MAIS j'ai remarqué que lorsque je veux utiliser la fonction setName sur un objet qui hérite de la classe MyFile alors les deux proposition ci-dessus ne donnent pas le même résultat, à savoir :
    • La première solution compile bien.
    • La deuxième provoque une erreur de compilation :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      debug/softpart.o: In function `ZN8SoftPart14setFromINIFileER9QSettings':
      D:/Qt/Projets/toto/toto/titi/softpart.cpp:27: undefined reference to `MyFile::setName(QString const&)'
      collect2: ld returned 1 exit status
      mingw32-make[1]: *** [debug\toto.exe] Error 1
      mingw32-make[1]: Leaving directory `D:/Qt/Projets/toto/toto'
      mingw32-make: *** [debug] Error 2


    J'ai donc deux questions :
    1. Pourquoi les 2 propositions ne donnent pas le même résultat ?
    2. Et surtout pourquoi la 2ème proposition ne compile pas ?


    Merci
    Dernière modification par Invité ; 14/08/2009 à 14h37.

  2. #2
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Tu peux employer la deuxieme possibilite, mais tu dois quand meme mettre la definition dans l'entete. Pour que le compilateur puisse appeler une fonction inline dans une unite de compilation, celle-ci doit en avoir la definition.

  3. #3
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Pourrais tu indiquer :
    - le(s) fichier(s) .cpp,
    - le(s) fichier(s) .hpp,
    - le processus de compilation.

  4. #4
    Invité
    Invité(e)
    Par défaut
    J'ai épuré le projet (qui est un projet Qt) et voici son contenu :
    • titi/derivedmyfile.cpp
    • titi/myfile.cpp
    • titi/softpart.cpp
    • titi/abstractsoftpart.h
    • titi/derivedmyfile.h
    • titi/myfile.h
    • titi/softpart.h
    • main.cpp
    • toto.pro


    Procédure de compilation classique pour les projets Qt (si vous connaissez Qt bien sûr) :
    • qmake -project
    • qmake
    • make


    Voici les fichiers
    • titi/derivedmyfile.cpp
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      #include "derivedmyfile.h"
       
      DerivedMyFile::DerivedMyFile()
      {
       
      }
    • titi/myfile.cpp
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #include "myfile.h"
       
      MyFile::MyFile()
      {
      }
       
      inline void MyFile::setName(const QString & name)
      {
          this->name = name;
      }
    • titi/softpart.cpp
      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
      #include <QDebug>
      #include <QSettings>
       
      #include "softpart.h"
       
      SoftPart::SoftPart()
      {
      }
       
      SoftPart::SoftPart(QSettings& iniFile)
      {
          setFromINIFile(iniFile);
      }
       
      inline DerivedMyFile& SoftPart::getFile()
      {
          return file;
      }
       
      void SoftPart::setFromINIFile(QSettings& iniFile)
      {
          QString fieldName;
       
          // key : name
          fieldName = "name";
          if(iniFile.contains(fieldName)){
              getFile().setName(iniFile.value(fieldName).toString());
          }
      }
    • titi/abstractsoftpart.h
      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
      #ifndef ABSTRACTSOFTPART_H
      #define ABSTRACTSOFTPART_H
       
      #include <QObject>
       
      class QSettings;
       
      class AbstractSoftPart : public QObject
      {
          Q_OBJECT
       
      public:
          virtual void setFromINIFile(QSettings& iniFile) = 0;
      };
       
      #endif
    • titi/derivedmyfile.h
      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
      #ifndef DERIVEDMYFILE_H
      #define DERIVEDMYFILE_H
       
      #include <myfile.h>
       
      class DerivedMyFile : public MyFile
      {
          Q_OBJECT
       
      public:
          DerivedMyFile();
       
      };
       
      #endif
    • titi/myfile.h
      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
      #ifndef MYFILE_H
      #define MYFILE_H
       
      #include <QObject>
       
      class MyFile : public QObject
      {
          Q_OBJECT
       
      public:
          MyFile();
       
          void setName(const QString & name);
       
      private:
          QString name;
      };
       
      #endif
    • titi/softpart.h
      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
      #ifndef SOFTPART_H
      #define SOFTPART_H
       
      #include <abstractsoftpart.h>
      #include <derivedmyfile.h>
       
      class QSettings;
       
      class SoftPart : public AbstractSoftPart
      {
          Q_OBJECT
       
      public:
          SoftPart();
          SoftPart(QSettings& iniFile);
       
          DerivedMyFile& getFile();
       
          void setFromINIFile(QSettings& iniFile);
       
      private:
          DerivedMyFile file;
       
      };
       
      #endif
    • main.cpp
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      #include <QApplication>
       
      int main(int argc, char *argv[])
      {
          QApplication app(argc, argv);
       
          return app.exec();
      }
    • toto.pro
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      TEMPLATE = app
      TARGET = 
      DEPENDPATH += . titi
      INCLUDEPATH += . titi
       
      # Input
      HEADERS += titi/abstractsoftpart.h \
                 titi/derivedmyfile.h \
                 titi/myfile.h \
                 titi/softpart.h
      SOURCES += main.cpp titi/derivedmyfile.cpp titi/myfile.cpp titi/softpart.cpp

  5. #5
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Par défaut
    Pourquoi utilises tu le mot inline ? alors que dand la premiere version tu ne le fais pas. Si tu enleve le inline sa fonctionne. De meme si tu veux utiliser le mot inline tu dois utiliser la premiere methode.
    Vous voulez participer aux Tutoriels, FAQ ou Traductions et faire partie de l'équipe Qt de Developpez.
    N'hésitez pas à me contacter par MP.

  6. #6
    Invité
    Invité(e)
    Par défaut
    J'utilise inline pour optimiser le code et il me semble que je le fais dans les 2 versions. En effet, même si je n'ai pas écrit explicitement le mot inline dans le 1ère version, la fonction est considérée tout comme car elle est définie dans le corps de la classe :
    http://bruce-eckel.developpez.com/li...e=inlines#L9.2

    Il me semble aussi que je peux utiliser les 2 méthodes, mais je dois surement me tromper étant donné cette erreur de compilation.

  7. #7
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    1) inline est un conseil, rien de plus.
    2) La deuxième solution ne donne pas la possibilité au compilateur d'inliner ton code
    3) Si ton constructeur par défaut est vide, pourquoi le mettre dans le .cpp au lieu de soit ne pas l'écrire explicitement ou de le laisser dans le .h ?

  8. #8
    Invité
    Invité(e)
    Par défaut
    1) J'avais cru comprendre
    2) Oui mais pourquoi, je crois que c'est la réponse que j'attends !
    3) Là j'ai épuré le code pour vous épargnez tout le code inutile pour ma question, mais c'est vrai, j'aurais pu épurer d'avantage.

  9. #9
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    2) Parce que le compilateur pour pouvoir inliner le code, c'est à dire grosso-modo faire l'insertion du code de la fonction/méthode en lieu et place de l'invocation, doit avoir accès au code source de la fonction/méthode à inliner.

    On pourrait imaginer un inlining tardif, c'est à dire binaire, où le compilateur irait chercher dans les (bibliothèques/fichiers objets) la fonction/méthode compilée, ce qui n'est plus du ressort du C++.

  10. #10
    Invité
    Invité(e)
    Par défaut
    J'ai un peu de mal à comprendre pourquoi le compilateur n'aurait pas accès au code de la fonction.
    Mais dans ce cas, à quoi sert la deuxième méthode, qui est possible si on en croit la traduction du tutoriel de Bruce Eckel (http://bruce-eckel.developpez.com/li...?page=sommaire) ?

  11. #11
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Citation Envoyé par titinetine Voir le message
    J'ai un peu de mal à comprendre pourquoi le compilateur n'aurait pas accès au code de la fonction.
    Mais dans ce cas, à quoi sert la deuxième méthode, qui est possible si on en croit la traduction du tutoriel de Bruce Eckel (http://bruce-eckel.developpez.com/li...?page=sommaire) ?
    Parce que le compilateur compile fichier cpp par fichier cpp, donc une fois qu'un fichier est fini, il ne peut pas aller chercher de code dans un fichier cpp compilé précédemment.
    La seule solution est alors d'utiliser lors de l'édition des liens une étape de recompilation, mais c'est encore un outil fragile et ça ne sera pas la panacée à un codage propre

  12. #12
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Le compilateur n'y a pas forcément accès si la bibliothèque est fournie compilée.

    Il ne dispose alors que des headers, qui doivent donc contenir le code à inliner.

  13. #13
    Invité
    Invité(e)
    Par défaut
    Ok, merci à tous pour vos explications.

Discussions similaires

  1. placer mes fonctions dans un fichier .c
    Par gastoncs dans le forum C
    Réponses: 2
    Dernier message: 29/04/2012, 01h49
  2. Où placer mes fonctions
    Par ulquiorra dans le forum POSIX
    Réponses: 27
    Dernier message: 26/06/2008, 13h53
  3. Mettre mes fonctions dans un meme script
    Par sparrow dans le forum Langage
    Réponses: 4
    Dernier message: 25/03/2006, 01h26
  4. Fonctions inlines et fichiers .lib
    Par michhh dans le forum C++
    Réponses: 3
    Dernier message: 05/07/2005, 03h09
  5. [EJB & WebServices] Où placer mes Facade et WS EndPoint?
    Par mauvais_karma dans le forum Services Web
    Réponses: 12
    Dernier message: 25/05/2005, 16h24

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