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

C++ Discussion :

Déclaration d'une fonction au milieu d'une autre fonction


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 63
    Points : 44
    Points
    44
    Par défaut Déclaration d'une fonction au milieu d'une autre fonction
    salut tt monde
    je voudrais savoir s il est possible de declarer une fonction au milieu d une autre fonction

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Salut,

    Tu peux appeler une fonction au sein de n'importe quelle autre, créer un bloc d'instruction au sein d'un autre, mais, non, tu ne peux ni déclarer ni définir une fonction au sein d'une autre...

    Pour information: la déclaration d'une fonction (le fait de dire qu'elle existe) se limite à la fourniture de son prototype ou de sa signature (void mafonct(type arg1); ) et la définition d'une fonction consiste à fournir les instructions qu'elle doit effectuer...

    De plus, en C++, seules les fonctions qui ont été valablement déclarées peuvent etre définies (à l'exception de la fonction main, qui est la seule à ne pas devoir etre déclarer et dont l'existance est obligatoire), et toute tentative d'appel d'une fonction déclarée mais non définie se soldera par un échec au niveau de l'édition de liens.

    *Typiquement* on sépare les déclarations des définitions, les déclaration dans les fichiers d'entete (*.h), et les définitions dans les fichiers code (*.cpp, *.cxx ...), mais il est possible - bien que ce ne soit vraiment pas recommandé - de mettre les déclarations et les définitions dans le meme fichier.

    Il faut alors garder en tete que seules les fonctions qui ont déjà été déclarées pourront etre appelées

    Ainsi, ce qui fonctionne sera du genre de:
    • un (ou plusieurs) fichier(s) d'entete contenant les déclarations et un (ou plusieurs) fichier(s) contenant les définitions:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      dans fichier.h 
      void mafonction();
      int ma_deuxieme_fonction();
      type ma_troisieme_fontion();
      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
      dans fichier.cpp
      #include "fichier.h" //indispensable pour que le compilateur sache
                                //que les fonctions existent ;)
      void mafonction()
      {
          //...
          int entier=ma_deuxieme_fonction();
          //...
          type montype=ma_troisieme_fonction();
          //...
      }
      int ma_deuxieme_fonction()
      {
          //...
          type montype=ma_troisieme_fonction();
          //aurait pu etre n'importe quelle fonction ;)
          //...
          return (un entier);
      }
      type ma_troisieme_fonction()
      {
          // peut appeler n'importe quelle fonction valablement déclarée, y compris
          // celles qui le sont par les inclusions "en cascade"
      }
    • La déclaration et leur définition des fonctions dans le meme fichier
      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
       
      // NOTA: dans ce cas, il est préférable de laisser toutes les déclaration
      // groupée (pour éviter le fait que l'une ou l'autre fonction ne soit pas 
      // connue (déclarée) à un moment donné ;) )
      void mafonction();
      int ma_deuxieme_fonction();
      type ma_troisieme_fontion();
      void mafonction()
      {
          //...
          int entier=ma_deuxieme_fonction();
          //...
          type montype=ma_troisieme_fonction();
          //...
      }
      int ma_deuxieme_fonction()
      {
          //...
          type montype=ma_troisieme_fonction();
          //aurait pu etre n'importe quelle fonction ;)
          //...
          return (un entier);
      }
      type ma_troisieme_fonction()
      {
          // peut appeler n'importe quelle fonction valablement déclarée, y compris
          // celles qui le sont par les inclusions "en cascade"
      }

    Dans les deux cas ci-dessus, l'appel des fonctions fonctionnera sans problème
    Ce qui ne fonctionnera pas:
    • la déclaration d'une fonction au sein d'une autre
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      void mafonction()
      {
          int mafonction;( int i, int y);
      }
    • La définition d'une fonction au sein d'une autre
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
       
      int mafonction2();
      void mafonction
      {
          //blabla
          int mafonction2()
          {
              //ce que doit faire mafonction2
          }
          //fin de mafonction
      }
    • La définition de fonction non déclarées
      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
      //déclaration des fonction
      void mafonction();
      void mafonct2();
      //définitions de fonctions
      void mafonction()
      {
         //OK
      }
      void mafonct2()
      {
          //OK
      }
      void mafonction3()
      {
         //Pas OK, mafonction3 n'a pas été déclarée
      }
    • l'appel à une fonction déclarée mais non définie
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      //déclarations des fonctions
      void mafonction();
      void mafonct2();
      void mafonct3();
      //définition des fonctions
      void mafonction()
      {
          //appel de mafonct3 qui n'est pas définie
         mafonct3();//Erreur à l'édition de liens
      }
      void mafonct2()
      {
          //blabla
      }


    Voici, en condencé et simplifié, les grosses lignes de ce qui peut etre fait et de ce qui ne peut pas etre fait
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    En promenant mon chien, deux petites appartés me sont venues à l'esprit:

    La premières est le "pourquoi créer une fonction", et la seconde est "mais pourquoi aurait il voulu définir une fonction au milieu d'une autre "...

    Alors, commençons par voir pourquoi il est intéressant de créer une fonction (d'un point de vue du programmeur, d'abord, de celui de "l'algorithmique" ensuite)

    Du point de vue du programmeur, on va généralement créer une fonction:
    • quand on en arrive à plus d'une cinquantaine de lignes dans une meme fonction, et que, pour une raison de pure lisiblité, on préfère en sortir deux fonctions plus petites
    • quand une suite d'instructions devra être utilisée à l'identique en de "nombreuses" occasions
    • quand on n'a pas le choix (acces en lecture ou en écriture aux membres privés d'une classe, par exemple)

    Du point de vue de l'algorithmique, c'est plus simple encore (du moins, à l'écriture): il suffit de garder en tete qu'une fonction ne devrait jamais etre responsable que d'une et une seule chose, mais qu'elle devrait bien le faire...

    Evidemment, en dehors du cas où il n'y a pas le choix, il est sans doute un peu excessif de créer une fonction pour "l'incrémentation de a" ou pour l'acces à l'élément suivant dans une liste créée à la main, alors que cela ne tiens qu'à une seule instruction : en toute chose exces est nuisible

    Pour la deuxième aparté, sur les quelques minutes qu'a duré la promenade, j'ai vu deux raisons majeurs qui auraient pu t'inciter à trouver un moyen de le faire:
    • on estime que la fonction "imbriquée" ne sera utile que dans la fonction dans laquelle tu veux l'imbriquer... mais à ce moment, il faut sérieusement se poser la question de savoir si on en est définitivement sur et certain
    • on voudrait autant que faire se peut éviter les phénomenes induits par l'appel d'une fonction, pour une raison de performances, principalement (les push et pop qui précedent et qui suivent l'appel d'une fonction)

    Dans le premier cas, on *peut* envisager - mais c'est loin d'être recommandé (je le redis: il faudra etre sur que l'on n'aura pas tendance à appeler la fonction "cachée" ailleurs - de ne déclarer qu'une ou deux fonctions dans un fichier d'entete, et de déclarer la fonction "cachée" dans le fichier d'implémentation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    dans fichier.h
    void mafonction();
    int ma_deuxieme_fonction();
    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
    dans fichier.cpp
    #include "fichier.h"
    void ma_fonction_cachee();
    void mafonction()
    {
        blabla
    }
    void ma_deuxieme_fonction()
    {
        blabla
    }
    void ma_fonction_cachee()
    {
        blabla
    }
    Dans le second cas, c'est plus simple encore...

    Il "suffit" de déclarer (et de définir) la fonction avec le mot clé inline

    inline est un mot clé qui conseille au compilateur de recopier le contenu d'une fonction partout où cette fonction est appelée...

    Cela peut rendre les choses bien plus rapides dans le cadre, par exemple, d'une fonction dont le seul but est de renvoyer la valeur d'un membre caché d'une classe.

    Par contre, il faut rester conscient du fait que le mot clé inline n'est jamais qu'un conseil fait au compilateur: libre à lui de décider s'il le prendra ou non en compte, avec meme parfois certaines surprises...

    Si le compilateur estime "l'inlining" injustifié, il ne l'appliquera simplement pas ... Sans compter sur le fait qu'il est, par exemple, incapable de l'appliquer sur les fonctions récursives

    Je ne voulais pas écrire un cours dans ce message, et il est déjà dramatiquement long...

    Je vous jure pourtant que j'ai essayé de me limiter à certains points de vue et à une explication "de principe", et à le faire le plus simple possible...

    Pour de plus amples informations, il ne faudra pas hésiter à poser des questions
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 28
    Points : 21
    Points
    21
    Par défaut
    Merci koala01 pour cette réponse

    Mais je voulais savoir, ce bout de code n'est-il pas légal ?

    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
    #include <iostream>
     
    void foo();
     
    int main ()
       {
       foo();
       }
     
    void foo()
       {
       void foo2();
       foo2();
       }
     
    void foo2()
       {
       std::cout << "foo2" << std::endl;
       }

    Mathieu

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    le void foo2(); qui se trouve dans foo() n'est pas légal...

    Simplement parce que cela représente la signature de foo2() (sa déclaration, autrement dit)...

    En C, il est possible de déclarer une fonction n'importe quand, du moment que c'est en dehors d'une autre, mais je ne suis pas sur que ce soit le cas en C++ (j'ai un doute)...

    Ainsi, sont légales:
    • d'office
      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
      void foo();
      void foo2();
      int main ()
         {
         foo();
         }
       
      void foo()
         {
       
         foo2();
         }
       
      void foo2()
         {
         std::cout << "foo2" << std::endl;
         }
    • surement en C (et peut etre en C++)
      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
      void foo();
       
      int main ()
         {
         foo();
         }
       
      void foo2(); 
      void foo()
         {
         foo2();
         }
       
      void foo2()
         {
         std::cout << "foo2" << std::endl;
         }
      dans le sens où la seule fonction qui aie besoin de connaitre foo2(), c'est foo()

    Mais, en tout état de cause foo2 doit etre déclarée
    • hors de toute fonction
    • Avant la premiere fonction qui y fait appel


    (mon doigt a glissé, provoquant l'envoi du message... sorry )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Réponses: 15
    Dernier message: 16/09/2009, 16h19
  2. [MySQL] Recherche fonction donnant tableau d'une ligne du résultat d'une requête
    Par zakuli dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 09/02/2009, 18h56
  3. Réponses: 3
    Dernier message: 12/12/2008, 10h47
  4. Réponses: 4
    Dernier message: 04/12/2008, 19h53
  5. Création d'une pause au milieu d'une application
    Par Henri dans le forum Windows
    Réponses: 3
    Dernier message: 23/03/2006, 16h31

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