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++

  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 303
    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 303
    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 ??

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

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 303
    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 303
    Billets dans le blog
    2
    Par défaut
    Pour t'aider il nous faudrait un peu plus de détails. Que sont Media_view et Pole_view? Quel est le mssage d'erreur exact?

    Au fait, quel compilateur utilises-tu?

  8. #8
    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
    Alors l'idée c'est qu'un Pôle contienne plusieurs Media. Chacun d'eux écoute un mouvement particulier qui entraîne une action. Par exemple, Pôle attend un mouvement de la main droite de bas en haut, pour faire apparaître les Media qui lui sont associés.

    Dans mes classes il n'y a pas grand chose, seulement des appels de méthodes qui elles-même ne font qu'afficher des cout (pour vérifier le bon déroulement). J'en suis encore à l'état de maquette en gros.

    Voici le code de Pole_view.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Pole_view::appear(void){
        //Apparition du Pole
     
        EventMovement *eventMovement;
        eventMovement = EventMovement::getInstance();
        eventMovement->addEventListener(this, "handRight_bottomTop", Pole_view::open);
    }
     
    void Pole_view::open(Pole_view *_this){
            //Centre le pôle et afficher un preload
            _this->controller->searchMedias();//Recherche les média associés, lorsque ce sera fait, controller appellera une methode LoadComplete de Pole_view
    }
    Pole_controller.cpp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void Pole_controller::searchMedias(void){
        cout << "Recherche des medias associes au pole..." << endl;
     
        view->loadComplete();
        displayMedias();
    }
     
    void Pole_controller::displayMedias(){
        cout << "Chargement des medias..." << endl;
        //Afficher chaque media, ex : Picture
        Picture_controller picture_ctrl(1);// 1 représente l'id mis en dur pour le moment
        //Picture_controller hérite de Media_controller, pour le moment il n'y a rien dans cette classe
    }

    Pour Media_view c'est sensiblement la même chose :

    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
    void Media_view::appear(){
        cout << "Integration du contenu" << endl;
     
        EventMovement *eventMovement;
        eventMovement = EventMovement::getInstance();
        eventMovement->addEventListener(this, "handRight_backFront", Media_view::open);
    }
     
    void Media_view::open(Media_view *_this){
            cout << "mouvement detecte -> le media s'approche du centre de l'ecran" << endl;
     
            //Centrer le media
            //Afficher un preload
            _this->controller->searchContent();
        }
    }
    Media_controller.cpp (Media_controller est une classe abstraite)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Media_controller::searchContent(void){
        cout << "Recherche le contenu associe au media..." << endl;
        //C'est tout pour le moment ;-)
    }

    Du coté du singleton EventMovement.cpp, c'est ce ce que j'ai mis dans le précédent post, normalement il y a la simulation de l'évènement et l'appel de la fonction envoyé en paramètre mais j'ai mis tout ça en commentaire pour tester, sans plus de resultat.

    Il en faut plus ou ça suffit ?
    J'utilise CodeBlocks comme éditeur/compilateur.

    J'espère que ça vous aidera à m'aider, merci

    Edit : J'oubliai le message d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: cannot convert 'Media_view*' to 'Pole_view*' in assignment

  9. #9
    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
    personne n'a d'idée ? Je suis bloquée à cause de ça et je ne comprends vraiment pas pourquoi...

    Merci d'avance pour votre aide précieuse :-)

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