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 :

Ecriture d'une fonction imbriquée dans une autre


Sujet :

C++

  1. #1
    Membre éclairé
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Par défaut Ecriture d'une fonction imbriquée dans une autre
    Bonjour, je travail avec CodeBlocks et gcc.

    Je n'ai pas programmé en C++ depuis des années. Il me semble qu'avant, on pouvait écrire une fonction à l'intèrieure d'une autre fonction. L'avantage, c'est que l'accessibilité et la portée de cette fonction "fille" est limitée à la fonction mère et à sa durée de vie. Je n'arrive pas à l'écrire.
    Exemple de ce que je voudrait écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void MaFonctionMere(void)
    {
       void MafonctionFille(void)
       {
       ... // code de la fonction fille
       }
     
    ... // code de la fonction mere avec appel à la fonction fille
    }
    Merci de me raffraichir la memoire sur cette possible écriture.

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Ce que tu veux faire n'est pas possible ni en C ni en C++
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 385
    Par défaut
    C'est seulement possible en GNU C, et je recommande de ne pas utiliser ce genre d'extension.

    Par contre, Visual C++ 8 accepte de me compiler ceci:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void TestClass(void)
    {
    	class UneClasseImbriquee {
    	public:
    		static void UneFonctionImbriquee(void)
    		{
    			std::cout << "Fonction Imbriquee!" << std::endl;
    		}
    	};
     
    	UneClasseImbriquee::UneFonctionImbriquee();
    }
    Mais j'ignore si ça passe sous gcc, ni ce qu'en dit la norme.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre éclairé
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Par défaut
    Je dois peut être confondre avec le pascal que j'ai pratiqué aussi il y a pas mal d'années.
    Je vais faire autrement.
    Merci pour vos réponses.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Citation Envoyé par kase74 Voir le message
    Je dois peut être confondre avec le pascal que j'ai pratiqué aussi il y a pas mal d'années.
    Oui, c'était faisable en Pascal mais cela n'apportait pas grand chose voire même cela compliquait la lecture (mais bon)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 385
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 385
    Par défaut
    Ce code passe sans problème sous MinGW (Dev-C++, gcc 3.4.2) :
    Code C++ : 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
    #include <iostream>
    #include <string>
     
    void TestClass(void)
    {
    	class UneClasseImbriquee {
    	public:
    		static void UneFonctionImbriquee(void)
    		{
    			std::cout << "Fonction Imbriquee!" << std::endl;
    		}
    	};
     
    	UneClasseImbriquee::UneFonctionImbriquee();
    }
     
    int main(void)
    {
    	TestClass();
    	std::string line;
    	std::cout << "Press [Enter] to quit" << std::endl;
    	std::getline(std::cin, line);
    	return 0;
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Oui, c'était faisable en Pascal mais cela n'apportait pas grand chose voire même cela compliquait la lecture (mais bon)
    Ca complique autant la lecture et ça a autant d'intérêt que les variables locales.

    Quand la fonction est très courte, pourquoi polluer l'extérieur avec une fonction dont on ne se servira qu'une seule fois, avec une fonction d'ordre supérieur style std::for_each(), std::find_if() ?

    Il faut se faire à l'idée qu'une fonction est une valeur comme les autres.

    ------

    Pour l'instant, tu es obligé d'écrire un foncteur explicite, mais bientôt avec la nouvelle norme du C++, tu pourras écrire des fonctions lambdas, ce qui est pratique si ta fonction est courte.

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Salut,

    Les classes locales sont autorisées par le standard.

    *Normalement*, tous les compilateurs devraient donc accepter un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void TestClass(void)
    {
    	class UneClasseImbriquee {
    	public:
    		static void UneFonctionImbriquee(void)
    		{
    			std::cout << "Fonction Imbriquee!" << std::endl;
    		}
    	};
     
    	UneClasseImbriquee::UneFonctionImbriquee();
    }
    Ensuite, pour ce qu'il en est des fonctions qui ne sont utilisées que de manière très ponctuelles, il reste toujours possible de n'envisager leur déclaration (et leur définition) que dans le fichier d'implémentation dans lequel elles sont utiles, au lieu de les déclarer dans le fichier d'en-tête.
    Citation Envoyé par HanLee Voir le message
    Quand la fonction est très courte, pourquoi polluer l'extérieur avec une fonction dont on ne se servira qu'une seule fois, avec une fonction d'ordre supérieur style std::for_each(), std::find_if() ?
    (snip)
    Si la raison qui peut pousser quelqu'un à factoriser un code qui n'est utilisé qu'une fois peut être débattue (peut-être est-ce simplement un "sous ensemble utile" de la fonction ), cela peut malgré tout rester du domaine de l'utile, ne serait-ce que pour permettre de distinguer clairement ce qui est fait.

    L'idée générale reste quand même qu'une fonction qui aurait plus d'une responsabilité en aurait trop, et, dans ce sens, une fonction qui - par la force des choses - devrait s'occuper de plusieurs points de vue de manière "simultanée" (ou presque) sera finalement plus facilement compréhensible si le comportement a été scindé en autant de "sous-fonctions" s'occupant chacune d'un point de vue particulier.

    A titre personnel, cela ne me gène aucunement... Le tout étant de trouver la granularité adéquate, entre une fonction de 200 lignes, et 150 fonctions de trois lignes
    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

  9. #9
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par koala01 Voir le message

    Ensuite, pour ce qu'il en est des fonctions qui ne sont utilisées que de manière très ponctuelles, il reste toujours possible de n'envisager leur déclaration (et leur définition) que dans le fichier d'implémentation dans lequel elles sont utiles, au lieu de les déclarer dans le fichier d'en-tête.

    Si la raison qui peut pousser quelqu'un à factoriser un code qui n'est utilisé qu'une fois peut être débattue (peut-être est-ce simplement un "sous ensemble utile" de la fonction ), cela peut malgré tout rester du domaine de l'utile, ne serait-ce que pour permettre de distinguer clairement ce qui est fait.
    Je parlais bien évidemment de fonctions très courtes, et qui sont jugées trop spécifique à un problème donné.
    Je n'ai pas dit qu'on a pas le droit de se tromper. Ce jugement peut demander un peu de recul. Mais un code, ça se travaille non ?

    -----

    On peut écrire un quicksort très lisible en max 4 lignes (suffit de choisir un bon langage), et pourtant bien peu malin celui qui n'en ferait pas une fonction externe utilisable par tout le monde!

    Comme j'ai dit chais plus où, une vraie bonne raison en C++ c'est qu'écrire un foncteur est lourd. En plus avec les algorithmes de la STL, ça marche pas les foncteurs locaux.

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 633
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 633
    Par défaut
    Nous sommes bien d'accord là dessus...

    Entre le fait de se dire qu'une fonction sera éventuellement réutilisée du fait de l'évolution des besoin, et celui de déterminer la meilleure granularité dans les fonctions, il reste énormément de place pour se poser la question de savoir s'il est opportun ou non de factoriser une partie du code

    Disons que j'ai simplement abordé le problème sous un angle différent (à l'opposé, même) du tien, mais que nous en arrivons pourtant au même résultat: dans certaines circonstances, nous nous garderons bien de factoriser un code donné, et dans d'autres, nous estimerons que les avantages sont suffisant pour décider de le faire

    Voilà encore une preuve - si besoin en était - que la programmation est un art dans lequel tout côtoie régulièrement son contraire, et où aucune règle personnelle ne peut être gravée dans le marbre de manière trop définitive
    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

  11. #11
    Membre éclairé
    Inscrit en
    Juin 2002
    Messages
    409
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 409
    Par défaut
    Bonjour à tous, je suis flatter que mon post suscite un tel débat.
    Pour amener mon petit gravier, je vais vous dire exactement la finalité de ce je voulais faire, ce qui, a mon avis, justifie de pouvoir jouir de l'imbrication de fonctions.
    Contexte : calcul d'un maillage dans un réseau de branches et de noeuds pour y appliquer (comme en électricité) la loi des noeuds/loi des mailles.
    Mon algo : (grosso modo)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Pour toute branche du reseau encore non traitee
       lancer la recherche des mailles englobant la branche en cours
    Fin
    Il est clair que la recherche des mailles est une fonction récursives. Son rôle est de parcourir toutes les branches connexes j'usqu'à ce que l'on reviennent sur la branche de départ.
    Je vous passe les détails et j'en reviens à notre sujet : Je voulais donc faire cette fonction récursive en l'imbriquant dans la fonction "principale".
    Avantages : (à mon humble avis)
    - dans ce cas la fonction est effectivement vouée à n'être appeler QUE par la fonction principale donc aucun lien avec l'extérieur, et tant mieux.
    - la fonction imbriquée peut utiliser les membres et fonctions membres de la classe dont la fonction principale fait partie. Ce que ne peut pas faire une fonction statique juste implémentée dans .cpp.
    - la fonction imbriquée peut utiliser des variables locales à la fonction principale. utile pour stocker les branches déjà usitées par exemple.
    - clarté du code, mais surtout, c'est que ici il est indispensable de scinder l'algo pour pouvoir faire la récursivité.

    Bon il se trouve que c'est pas possible, tant pis ! Voici au final comment j'ai fais :
    - J'ai fais ma fonction récursive comme fonction membre privée de ma classe. Malheureusement elle apparaîtra dans le .h ou le .a.
    - J'ai passé toutes les variables nécessaires au fonctionnement par variable pour conserver les modifs à la sortie de la fonction récursive.

    Et voilà, ca marche très bien comme ça. On a une solution alors ça ne vaut pas la peine de modifier la norme pour ça, en tout cas pas juste pour moi

    Merci à tous pour vos contributions.

  12. #12
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Citation Envoyé par HanLee Voir le message
    Il faut se faire à l'idée qu'une fonction est une valeur comme les autres.
    C'est ce qui se passe comme tu le dis avec les fonctions lambda de C++0x, mais encore plus dans Boost avec Boost.Phoenix/Proto/Spirit/Fusion qui tendent vers des manières très agréables que l'on a en programmation fonctionnelle (fonction lambda qu'on déclare+définit en une passe et ce juste quand on en a besoin, une espèce de filtrage aussi, ...).

    Ce qui peut être repoussant, c'est la syntaxe à adopter pour insérer tout ça en C++

  13. #13
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Attends, mais ce qui m'énerve c'est que C# a des fonctions lambda polymorphe et finalement en C++ on n'aura que les monomorphes.

    Or dans ce papier page 10 : http://www.research.att.com/~bs/N196...xpressions.pdf, ils disaient que techniquement yaurait pas de soucis pour rendre ça polymorphe (et donc on aurait pas besoin de préciser le type des arguments !).

  14. #14
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Citation Envoyé par HanLee Voir le message
    Attends, mais ce qui m'énerve c'est que C# a des fonctions lambda polymorphe et finalement en C++ on n'aura que les monomorphes.

    Or dans ce papier page 10 : http://www.research.att.com/~bs/N196...xpressions.pdf, ils disaient que techniquement yaurait pas de soucis pour rendre ça polymorphe (et donc on aurait pas besoin de préciser le type des arguments !).
    Va falloir bosser avec Boost.Phoenix/Lambda pour ça

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 05/04/2011, 09h06
  2. [AJAX] [XAJAX] Lancer une fonction JS dans une fonction AJAX
    Par sixieme-sens dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 26/12/2008, 16h26
  3. Réponses: 1
    Dernier message: 25/10/2007, 22h25
  4. Réponses: 10
    Dernier message: 18/04/2007, 18h17
  5. [VBA-E] Une fonction Excel dans une fonction VBA
    Par laloune dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 14/07/2006, 11h21

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