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 :

Passage de fonction en argument à une autre classe


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Par défaut Passage de fonction en argument à une autre classe
    Bonjour,

    je débute en C++ et je suis fasse à un problème depuis hier soir et je n'arrive pas à trouver une solution "propre".

    Alors j'ai un singleton EventMovement, et une classe Main_controller.
    Depuis Main, je cherche à faire quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Main_controller::Main_controller(void){
        EventMovement *eventMovement;
        eventMovement = EventMovement::getInstance ();
     
        //Ce que je cherche à faire :
        eventMovement->addEventListener("haut_bas", maFonction);
    }
     
    void Main_controller::maFonction(void){
        autreFonctionDeMain();
    }
    et dans mon singleton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void addEventListener(std::string event_, void(*func_)(void)){
                func_();
    }

    Mais évidemment ça ne marche pas... J'avais espéré qu'en passant la fonction par référence, ça marcherai tout seul ;-) Mais comme j'ai pas encore tout compris aux références, adresses,...

    Finalement j'ai trouvé une solution, mais qui est un peu... crade :

    Main_controller :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Main_controller::Main_controller(void){
        EventMovement *eventMovement;
        eventMovement = EventMovement::getInstance ();
     
        eventMovement->addEventListener(this, "haut_bas", Main_controller::maFonction);
    }
     
    static void Main_controller::maFonction(Main_controller *_this){
        _this->autreMethodeDeMain();
    }
    par contre du côté du singleton, le problème est que je dois connaitre le type des arguments, et du coup importer le Main_controller.h. Il faudra alors que je crée autant d'addEventListener que de classe qui l'utiliseront... Ce n'est pas très pratique :

    Singleton :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void addEventListener(Main_controller*objet, std::string event_, void(*func_)(Main_controller *_this)){
                func_(objet);
    }
    A votre avis, comment pourrais-je faire ? N'y a-t'il pas moyen de faire plus simple ? ou peut-on passer un argument dont le type est inconnu (ce serait déjà pas mal) ?

    Merci beaucoup de votre aide,
    à bientôt

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    La FAQ explique comment on manipule les pointeur de fonctions avec arguments :
    http://cpp.developpez.com/cours/cpp/?page=page_6#LVI-L

    Ceci dit, une méthode add event listner n'a pas vocation à invoquer la fonction/méthode qu'on lui passe en paramètre mais plutôt de la stocker en vue d'un appel plus tard dans un certain contexte.

  3. #3
    Membre averti
    Femme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Par défaut
    Merci mais j'ai déjà essayé avec les pointeurs de fonctions :

    Main_controller.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    eventMovement->addEventListener("haut_bas", maFonction);
    EventMovement.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void addEventListener(std::string event_, void(&func_)(void)){
                func_();
    }
    J'ai toujours la même erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: no matching function for call to 'EventMovement::addEventListener(const char [3], <unresolved overloaded function type>)'|
    Je pense que ça marcherai si les méthodes étaient dans la même classe, mais ce n'est pas le cas... Où alors je m'y prends mal mais j'ai essayé tout un tas de choses sans résultat.

    D'autres idées ?

    Edit : effectivement c'est prévu que je stocke la fonction pour l'appeler plus tard (lorsque le mouvement est détecté), ici j'ai simplifié mon code, mais ça reviens au même je pense...

  4. #4
    Membre averti
    Femme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Par défaut
    Ca y est j'ai trouvé quelque chose de pas trop mal ! :-) Grand merci aux templates...

    je suis partie de l'idée d'une classe statique (cf premier post) ce qui donne maintenant :

    Main_controller :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Main_controller::Main_controller(void){
        EventMovement *eventMovement;
        eventMovement = EventMovement::getInstance ();
     
        eventMovement->addEventListener(this, "haut_bas", Main_controller::maFonction);
    }
     
    static void Main_controller::maFonction(Main_controller *_this){
        _this->autreMethodeDeMain();
    }

    EventMovement : (Singleton)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <typename Type> void addEventListener(Type *objet_, std::string event_, void(*func_)(Type *_this)){
        func_(objet_);
    }

    Et ça fonctionne :-) C'est déjà une bonne chose de faite, mais maintenant il faut que je stocke ces valeurs dans un tableau... J'aurai voulu quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    monTableau[0].objet = objet_;
    monTableau[0].func = func_;
    monTableau[0].event = event_;
    Je suis donc passé par une structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename TypeStruct> struct struct_monTableau{
                TypeStruct *objet;
                void(*func)(TypeStruct *_this);
                std::string event;
    };
    mais je n'arrive pas à déclarer mon tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<struct struct_monTableau> monTableau;
    me renvoi cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: template argument required for 'struct struct_monTableau'
    je ne comprends pas bien pourquoi.. quelqu'un pourrait-il m'aider s'il vous plaît ?

  5. #5
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 292
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    une vector ne peut pas contenir une classe template non spécialisée. Ce que tu veux faire n'est donc pas possible tel quel. En revanche - pour donner un exemple didactique - le code suivant fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector< struct_monTableau<int> > monTableau;
    Sinon, pour passer des pointeurs de fonctions, tu peux utiliser std::bind et std::function (si ton compilateur le supporte, comme par exemple visual studio 2010 ou une version récente de gcc). Un exemple didactique (inspiré de la FAQ c++0x de B.S):
    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
    #include <iostream>
    #include <functional>
     
    struct X {
    	void foo(void) { std::cout << "foo" << std::endl; }
    };
     
    main()
    {
    	std::function<void (X*)> f;
    	f = &X::foo; // pointer to member function
     
    	X x;
    	f(&x);	// call X::foo()
    }

  6. #6
    Membre averti
    Femme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 19
    Par défaut
    Merci de ton aide r0d, mais je n'ai pas réussi à faire fonctionner ton code :-s
    Finalement j'ai enregistré mes classes dans différents tableaux... c'est pas tiptop mais je n'ai plus vraiment le temps de faire mieux (projet à rendre la semaine prochaine, et y a encore du boulot :-s)

    Maintenant j'ai une erreur toute bête... mais alors là je vois vraiment pas ce que je fais de mal !

    J'ai donc créé mes tableaux comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <typename TypeStruct> struct struct_objectFunction{
                TypeStruct *object;
                void(*func)(TypeStruct *obj);
    };
     
    std::vector<struct struct_objectFunction <Pole_view> > eventPole_handRight_bottomTop;
    std::vector<struct struct_objectFunction <Media_view> > eventMedia_handRight_backFront;
    et dans mon addEventListener (je sais, c'est pas très propre, mais il faut que j'avance !!)

    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
                if(strcmp(event_.c_str(), "handRight_bottomTop") == 0){
                    if(strcmp(typeid(object_).name(), "P9Pole_view") == 0){
                        struct_objectFunction <Pole_view> objFunc;
                        objFunc.object = object_; // Erreur
                        objFunc.func   = func_;
                        eventPole_handRight_bottomTop.push_back(objFunc);
                    }
                }else if(strcmp(event_.c_str(), "handRight_backFront") == 0){
                    if(strcmp(typeid(object_).name(), "P10Media_view") == 0){
                            struct_objectFunction <Media_view> objFunc2;
                            objFunc2.object = object_;
                            objFunc2.func   = func_;
                            eventMedia_handRight_backFront.push_back(objFunc2);
                    }
                }
    Et là cet idiot de compilateur me dit qu'il ne peut pas convertir Media_view en Pole_view, comme s'il exécutait les if sans tenir compte des conditions. Pourtant il le faisait très bien quand il n'y en avait qu'une, et d'ailleurs si je mets en commentaire le contenu qui pose problème en ajoutant des cout, on voit bien qu'il fonctionne comme il faut...

    Je n'y comprends plus rien... peut-être est-il l'heure d'aller se coucher...

    Encore un peu d'aide s'il vous plaît ??

Discussions similaires

  1. Réponses: 3
    Dernier message: 19/12/2014, 17h03
  2. Réponses: 8
    Dernier message: 05/04/2011, 08h06
  3. Passage d'argument dans une fonction d'une autre classe.
    Par lavince dans le forum Général Python
    Réponses: 5
    Dernier message: 13/09/2008, 22h16
  4. Réponses: 2
    Dernier message: 22/12/2006, 11h35
  5. Probleme d'apel de fonction dans une autre classe
    Par freecell31 dans le forum MFC
    Réponses: 24
    Dernier message: 13/05/2006, 11h34

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