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 :

pointeur vers fonctions


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 17
    Par défaut pointeur vers fonctions
    Bonjour a tous!

    Je suis entrain de développer une librairie d'interface graphique opengl opensource (https://github.com/3dsman/snice_ui) qui avance bien mais je viens de tomber sur un problème que je n'avais pas anticipé dans mon architecture...

    En gros quand je rée un bouton par exemple je peut créer une fonction de callback pour exécuter différentes actions (ici je me contente d'afficher le bouton enfoncé):

    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
     
    // fonction de callback du bouton
    void test(W_button* caller)
    {
        caller->SetPressed(true);
        std::cout<<"le bouton a été appuyé";
    };
     
    int main(int argc, char *argv[])
    {
        // creation de la fenetre avec un viewport par default
        pSnice_UI = new Snice_UI(800,600,50);
     
        // recuperaion du viewport
        pViewport = pSnice_UI->GetViewport();
     
        // creation d'un bouton
        pValid = new W_button(200,100, 120,20, "COOL");
     
        // attache du bouton au viewport
        pViewport->AddChild(pValid);
     
        //signalisation de la fonction de callback
        pValid->OnClick(test);
     
        [...]
    }
    Dans la classe W_button j'ai (en version tres tres epurée ):
    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
     
    class W_button : public UI_widget
    {
    protected
      void (*onClick)(W_button* caller) = NULL;
     
    public:
    void W_button::OnClick(void (*function)(W_button* caller))
    {
        onClick = function;
    }
     
    UI_base* W_button::OnLButtonUp(int x, int y)
    {
            if (Hittest(x,y))
            {
                if(onClick) onClick(this);
            }
        return 0;
    }
    }
    Tout ca marche tres bien dans le ca ou je crée tous les boutons a la main mais j'aimerais bieen maintenant avoir des dialog boxes (un widget de texte et deux boutons par exemple).
    Le probleme c'est que mes fonctions de callback ne pointent pas sur des fonctions de classe.
    Je ne peut donc pas par exemple avoir une classe D_toto qui aurait une fonction test pour recuperer le callback du bouton...

    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
     
    void D_toto::D_toto()
    {
        // creation d'un bouton
        pValid = new W_button(200,100, 120,20, "COOL");
     
        // attache du bouton a ma dialogbox
        AddChild(pValid);
     
        //signalisation de la fonction de callback
        pValid->OnClick(this->test);
    }
     
    void D_toto::test(W_button* caller)
    {
        caller->SetPressed(true);
        std::cout<<"le bouton a été appuyé";
    };
    Je vois bien que j'ai fait une erreur d'architecture mais je ne vois pas de solution pour contourner le problème...
    Comment ca se fait ce genre de trucs en général?

    Merci d'avance de vos réponses.

  2. #2
    Membre émérite
    Homme Profil pro
    Recherche du travail
    Inscrit en
    Août 2004
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Recherche du travail

    Informations forums :
    Inscription : Août 2004
    Messages : 561

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 17
    Par défaut
    Je ne vois pas trop ce que ca changerais dans mon cas.
    Pourrais tu m'indiquer comment l'utiliser ici stp?

    Dans tous les cas une fonction membre devra etre stockée dans un autre variable non?
    std::function<void(const D_toto&, int)> onClick = &D_toto::OnClick;

    Par contre je viens de voir dans un de tes liens l'utilisation de fonctions statiques avec un handler sur l'objet appelé:
    https://isocpp.org/wiki/faq/pointers...fnptr-vs-fnptr

    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
     
    class D_toto : public UI_dialog
    {
    protected
        void OnBtnClick(W_button* caller);
        W_button pValid;
        static D_toto* handler;
    public:
        static void OnBtnClickStat(W_button* caller);
    }
     
    void D_toto::D_toto()
    {
        // creation d'un bouton
        pValid = new W_button(200,100, 120,20, "COOL");
     
        // attache du bouton a ma dialogbox
        AddChild(pValid);
     
        //signalisation de la fonction de callback
        pValid->OnClick(OnBtnClickStat);
    }
     
    void OnBtnClickStat(W_button* caller)
    {
        // on verifie que le handler est bien remplis
        if (D_toto::handler)
            D_toto::handler->OnBtnClick(W_button* caller);
    }
    Sachant que je peut remplir le handler avec un pointeur sur l'objet courant (ma boite de dialogue) ca peut le faire non?

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    std::function est une classe générique qui prend n'importe quoi qui possède operator(): lambda, fonction, foncteur.
    std::mem_fn est une fonction qui retourne un foncteur pour appeler une fonction membre.

    Donc le type de caller devient std::function<void(W_button*)>.

    Et pValid->OnClick(this->test); devient pValid->OnClick([this](W_button*){ this->test(); });.

  5. #5
    Membre émérite
    Homme Profil pro
    Recherche du travail
    Inscrit en
    Août 2004
    Messages
    561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Recherche du travail

    Informations forums :
    Inscription : Août 2004
    Messages : 561
    Par défaut
    Utiliser la std est préférable car elle apporte des sécurités notamment l'exception bad_function_call. Disons que c'est plus orienté c++, c'est comme pour le cast des types. On privilégiera l'utilisation de static_cast au lieu du cast c.

    Dans tous les cas une fonction membre devra etre stockée dans un autre variable non?
    std::function<void(const D_toto&, int)> onClick = &D_toto::OnClick;
    Tu peux utiliser le type std::function<void(const D_toto&, int)> dans l'argument.
    Bien évidement dans tous les cas il y aura copie de pointeur. Je te rappelle que le c++ passe par défaut les arguments par copie.

    Par contre je viens de voir dans un de tes liens l'utilisation de fonctions statiques avec un handler sur l'objet appelé:
    C'est sûrement pas la meilleur solution dans ton cas... Relis les liens.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 17
    Par défaut
    La vache, je suis un peu largué :p

    Quand je remplace mon pValid->OnClick(this->test); par pValid->OnClick([this]{ this->test(); }); j'ai une erreur de "no matching function for call to test()" ce qui me semble logique puisque la fonction test est declarée avec un argument:
    void D_toto::test(W_button* caller)

    Si je met plutot pValid->OnClick([this]{ this->test(W_button* caller); }); alors je me prends une erreur "expected primary-expresion before '*' token"

    La je pige plus trop le concept

  7. #7
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    [this]{ this->test(); } est une expression, dont la valeur est une lambda qui prend this en référence dans son contexte de déclaration, n'a pas d'argument, et dont l'exécution consiste à l'évaluation de l'expression this->test().
    C'est en gros un pointeur de fonction.

    Si test est une fonction libre (non membre, donc), c'est probablement qu'il faut utiliser [this]{ test(*this); } ou [this]{ test(this); }. éventuellement, il faut rectifier la fonction.
    Si elle attend un argument autre que le fameux this, il faut trouver la valeur à lui donner.

Discussions similaires

  1. Pointeur vers fonction membre
    Par poukill dans le forum C++
    Réponses: 20
    Dernier message: 17/01/2011, 10h08
  2. Utilité d'un pointeur vers une fonction ?
    Par Nasky dans le forum C
    Réponses: 10
    Dernier message: 20/03/2010, 19h54
  3. Pointeur vers une table dans une fonction
    Par Chatbour dans le forum Oracle
    Réponses: 2
    Dernier message: 03/05/2007, 12h28
  4. Réponses: 12
    Dernier message: 30/06/2006, 16h46
  5. Pointeur vers fonction
    Par flopaname dans le forum Langage
    Réponses: 3
    Dernier message: 23/06/2005, 15h46

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