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 :

Passer une fonction en paramètre


Sujet :

Langage C++

  1. #1
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut Passer une fonction en paramètre
    Bonjour à vous !

    Suite à ce post et à l'aide de celui-ci, j'ai souhaité améliorer la simplicité d'ajout de nouvelles "pages" à mon programme.

    Page.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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #include <vector>
    #include <string>
    #include <functional>
    #include "Model.h"
     
    class Page
    {
    //Définit le type à stocker
        enum CallType
        {
            INFO,
            ACTION
        };
    //Pour stocker à la fois la fonction et sa définition
        struct TxtAndFun
        {
            TxtAndFun( const std::string& txt, std::function< void() > fun ) : txt( txt ), fun( fun ) {}
            std::string txt;
            std::function< void() > fun;
        };
     
    public:
        virtual ~Page() {}
        void display();
        void work();
    //Ajouter une fonction ou simplement une information
    protected:
        void add( const std::string& txt, std::function< void() > fun );
        void add( const std::string& txt );
     
    private:
        std::vector< TxtAndFun >   actions_;
        std::vector< std::string >  infos_;
    //Pour garder l'ordre des informations entrées
        std::vector< CallType > call_order_;
    };
    PageSummary.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include "Page.h"
    //Creation d'une nouvelle page
    class Summary : public Page
    {
    public:
        Summary( Model& model )
        {
            add( "Titre" );
            add( "Make Job", std::bind( &Model::change_page, &model, PageType::MAKE_JOB ));
            add( "Quit", std::bind( &Model::prog_quit, &model ));
        }
    };
    J'ai pour but de n'avoir pas à me préoccuper de la réponse attendue par l'utilisateur. Ce qui permettrait de changer l'interface en modifiant seulement l'ordre de mes fonctions "add".

    Console
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Titre
    1 - Make Job
    0 - Quit
    Ceci fonctionne bien, cependant je n'arrive pas a passer directement une fonction en paramètre pour la "binder" dans la classe Page.

    Je suis contraint de le faire avant de l'envoyer en paramètre. Ni aurait t'il pas un moyen d'avoir simplement ce qui suis en fonction ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Summary : public Page
    {
    public:
        Summary( Model& model )
        {
            add( "Titre" );
            add( "Add Job", model.change_page( PageType::ADD_JOB ));
            add( "Quit", model.prog_quit );
        }
    };
    De plus je ne comprends pas bien le fait de devoir écrire "&Model::change_page, &model" pour enregistrer cette fonction "model.prog_quit()" (Que j'ai obtenue en tâtonnant )

    Merci d'avance.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    C'est une fonction membre que tu bindes ici.
    Pour pouvoir l'appeler sans lui re-passer un "this" à chaque fois, il faut le mémoriser avec dans le binding.
    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.

  3. #3
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par PilloBuenaGente Voir le message
    De plus je ne comprends pas bien le fait de devoir écrire "&Model::change_page, &model" pour enregistrer cette fonction "model.prog_quit()" (Que j'ai obtenue en tâtonnant )

    Merci d'avance.
    Hello,

    Tu as plusieurs possibilités, soit un std::bind (boost::bind si pas de C++11), soit passer une lambda, soit un foncteur (plus lourd à déclarer mais en général plus facilement réutilisable)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    add( "Make Job", std::bind( &Model::change_page, &model, PageType::MAKE_JOB ));
    add( "Make Job", [&model]() { model.change_page(PageType::MAKE_JOB));
    un std::function est l'équivalent d'un foncteur : un pointeur de fonction avec un contexte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::bind( &Model::change_page, &model, PageType::MAKE_JOB )
    Tu stockes des fonctions de prenant aucun paramètres, std::bind permet de prendre une fonction, de fixer un contexte et retourne un std::function.
    Ici tu fixes deux les paramètres de change_page : this et un paramètre de type PageType.
    std::bind te retourne ici un objet utilisable comme une fonction libre ne prenant aucun argument.

    Une fonction membre est identique à une fonction libre, elle prend juste this en premier paramètre, mais c'est caché par la syntaxe.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    obj.foo();
    // est équivalent à 
    foo(obj);
    (La convention d'appel est différente, et il est interdit de remplacer l'un par l'autre directement, mais dans le fond, c'est équivalent).

  4. #4
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Non, certain langages, Haskell par exemple, permette ce que tu veux faire, mais en C++ le plus simple et proche de ce que tu veux que tu pourras avoir est d'utiliser une lambda, C++11 donc (ou boost.phoenix en C++03 mais ça reste lourd en un sens).

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    J'ai moi aussi implémenté un système de "page" dans un de mes projets.

    En gros chaque "page" détermine la manière dont les événements seront traités et l'affichage sur l'écran.

    Je ne sais pas si utiliser/binder un langage de script pourrait te simplifier la tâche.

    Par exemple, j'ai un code en Lua qui est appelé par mon programme C++ et qui détermine ce qui doit être fait lors d'événements :
    ex : "entrer" (quand on "entre" dans la page), "quit", "draw" (quand on souhaite dessiner la page, etc...

    Ceci m'évite d'avoir un nombre très important de pointeurs sur fonctions ou d'avoir de multiples classes pour les pages.

  6. #6
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Merci à vous !

    Lua n'aurait pas tendance à compliquer les choses pour un petit projet ?

    Les lambdas semblent correspondre à mes besoins.


    Je ne sais pas si cette portion est aux normes, mais elle semble faciliter la conception des pages.

    Program.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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #include "Page.cpp"
     
    enum Id : char//Nom des pages
    {
        SUMMARY,
        NEW_JOB,
        NEW_INTERIM
    };
     
    void Program::load( const char id )//Lancer une page
    {
        Page< Data > p( data_ );//Déclaration d'une nouvelle page
     
        switch( id )//Afficher la page et enregistrer les liens
        {
        case SUMMARY:
            p.title( "Summary" );//Créer une entête pour le titre
            p.link( []( Data& data )->void{ data.page_id_ = NEW_JOB; }, "1", "New worked day" );//Executer la fonction avec l'entrée "1"
            p.last_line();//Ecrire sur la dernière ligne
            p.link( []( Data& data )->void{ data.program_run_ = false; }, "0", "Quit" );
            break;
     
        case NEW_JOB:
            p.title( "New Job" );
            p.print( "Enter job's name" );
            p.last_line();
            p.link( []( Data& data )->void{ data.page_id_ = SUMMARY; }, "0", "Summary" );
            p.shift( 20 );
            p.link( []( Data& data )->void{ data.program_run_= false; }, "00", "Quit" );
            p.name( []( Data& data )->void{ data.temp_name = data.input_; data.page_id_ = NEW_INTERIM; } );//Si l'on saisi un nom
            break;
     
        case NEW_Date:
            p.title( "New Date" );
            p.print( "Enter date worked with", data_.temp_name );
            p.last_line();
            p.link( []( Data& data )->void{ data.page_id_ = SUMMARY; }, "0", "Summary" );
        }
     
        p.execute( data_.input_ );//Executer le lien choisi
    }
     
    void Program::execute()
    {
        data_.program_run_ = true;
        data_.page_id_ = Id::SUMMARY;
     
        while( data_.program_run_ )
        {
            load( data_.page_id_ );
        }
    }

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

Discussions similaires

  1. Réponses: 16
    Dernier message: 26/05/2009, 13h32
  2. Passer une fonction en paramètre, sans delegate
    Par deejay2221 dans le forum C#
    Réponses: 8
    Dernier message: 26/03/2009, 20h22
  3. Réponses: 15
    Dernier message: 02/08/2007, 11h17
  4. Passer une fonction en paramètre ...
    Par Freeze dans le forum C++Builder
    Réponses: 2
    Dernier message: 14/10/2005, 16h51
  5. [Conception] Passer une fonction en paramètre
    Par pejay dans le forum Langage
    Réponses: 9
    Dernier message: 09/12/2004, 13h58

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