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 :

Passer une méthode d'une classe en argument d'une autre méthode dans une autre classe ?


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur
    Inscrit en
    Juillet 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Juillet 2019
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Passer une méthode d'une classe en argument d'une autre méthode dans une autre classe ?
    Bonjour,
    j'ai un petit souci (car suis pas bon en c++) et je suis certain de trouver ici la réponse !
    voila j'ai une class :
    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
     
    class Find_Root
    {
        public:
            Find_Root();
            virtual ~Find_Root();
            double Root(double (*Fx)(double), double Xi, double Xf, double Precision, int MaxIter);
    };
     
    double Find_Root::Root(double (*Fx)(double), double Xi, double Xf, double Precision, int MaxIter)
    {  
    double solution;
    // trouve la solution
    return solution;
    }
    et dans mon main une fonction f :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #include "Find_Root.h"
    double f(double X) return X*X+2;
     
    int main()
    {
        Find_Root R;
       cout<<R.Root(f,0,5,1e-6,1000);
    }
    cela me donne bien racine 2... 1.414... pas de pb la fonction f est bien transmise à Find_Root.
    Le problème arrive lorsque la fonction f est définie dans une autre class et pas défini en global comme avant... J'ai donc une class nomée Fct :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class Fct
    {
      public:
            Fct();
            virtual ~Fct();   
            double f(double X) return X*X+2;
      protected:
    }
    et dans mon main je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int main()
    {
    Fct Func;
    Find_Root R;  
    cout<<R.Root(Func.f,0,5,1e-6,1000);
    }
    ET là c'est le drame ... il reconnait pas le type de f lorsque je passe Func.f : <unresolved overloaded function type> ??? et
    Impossible de compiler
    ||=== Build: Debug in Raccord (compiler: GNU GCC Compiler) ===|
    C:\Users\jpc\Desktop\Raccord\main.cpp||In function 'int main()'|
    C:\Users\jpc\Desktop\Raccord\main.cpp|44|error: no matching function for call to 'Find_Root::Root(<unresolved overloaded function type>, int, int, double, int)'|
    C:\Users\jpc\Desktop\Raccord\Find_Root.h|18|note: candidate: double Find_Root::Root(double (*)(double), double, double, double, int)|
    C:\Users\jpc\Desktop\Raccord\Find_Root.h|18|note: no known conversion for argument 1 from '<unresolved overloaded function type>' to 'double (*)(double)'|
    ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|

    J'aimerais pouvoir passer à R.Root n'importe quelle fonction f qu'elle soit définie comme au début ... "double f(double X) return X*X+2;" ou dans une class quelconque pourvue qu'elle soit de type double f(double) ...

    pourquoi ça ne marche pas car dans les deux cas le type de la fonction f est le même double f(double) pourtant !!?
    et comment y remédier ??

    Merci d'avance pour vos réponses,
    cordialement
    JPC

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Cela pourrait se résoudre avec le mot-clé static, qui permet de se passer d'une instance de la classe. Car, oui, le problème vient de là : on ne peut pas appeler Fct.f directement, il faut une instance pour pouvoir appeler la méthode.

    Il faut réfléchir plus globalement sur le design. Le code n'est pas peut-être pas un code complet, mais pourquoi faire des classes ? Il n'y a pas de données membres, visiblement pas de polymorphisme (le destructeur est virtual mais ça ne sert à rien). Des namespaces avec des fonctions libres, ça serait pas suffisant ?

    Exemple :
    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
    namespace equation
    {
     
    using SolverFunction = double(double);
     
    double find_root(SolverFunction Fx, double, double, double, int)
    {
        return Fx(0.0);
    }
     
    namespace functions
    {
    double f(double X) {
        return X * X + 2;
    }
    }
     
    } // namespace equation
     
    #include <iostream>
     
    int main()
    {
        std::cout << equation::find_root(equation::functions::f, 0, 0, 0, 0);
    }

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur
    Inscrit en
    Juillet 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Juillet 2019
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Cela pourrait se résoudre avec le mot-clé static
    Oui ! Merci pour votre réponse, mais le code n'est effectivement pas complet (loin de là)!... En fait si je déclare dans mon exemple initial :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static double f(double X) return X*X+2;
    ca compile ! par contre j'ai encore un problème ... car en réalité la fonction f(double X) est plus complexe, elle fait appelle à d'autres fonctions et paramètres de la <class Fct> via le pointeur ... this->
    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class Fct
    {
      public:
            Fct();
            virtual ~Fct();   
            double f(double X)  {return ((this->param1) * (this-> H(X)));}
            double H(double X);                               // <---- fonction de X mais aussi des paramètres stockés dans les variables protected de la class...
            void Set_P1(double p1) {this->param1=p1;}  
    protected:
            double param1=0.1; 
            double param2;
            ...
    }
    du coup si je mets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static double f(double X)  {return ((this->param1) * (this-> H(X)));}
    Le compilo m’envoi balader ...

    "... |21|error: 'this' is unavailable for static member functions|"

    je ne vois vraiment pas du tout comment m'en sortir... Merci de votre aide.

    cordialement,
    JP

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Et c'est normal.

    Il y a un problème de conception là. Une fonction libre et une méthode (non statique) d'une classe n'ont pas grand chose à voir. Tu ne peux pas atteindre l'un et l'autre à la fois. Tu as deux solutions :
    - Passer un objet qui répond à une interface particulière en premier paramètre de FindRoot().
    Exemple :
    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
    struct Solver {
        virtual double f() = 0;
    };
     
    double FindRoot(Solver& s) {
        return s.f();
    }
     
    struct MySolver : Solver {
        double f() override {
            return 42.0f;
        }
    };
     
    #include <iostream>
     
    int main()
    {
        MySolver solver;
        std::cout << FindRoot(solver) << '\n';
    }
    - Utiliser une lambda fonction en premier argument pour wrapper l'appel à une méthode sur un objet
    Exemple :
    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
    #include <functional>
     
    using Solver = std::function<double(void)>;
     
    double FindRoot(Solver s) {
        return s();
    }
     
    struct Fct {
        double f() {
            return 17.0;
        }
    };
     
    #include <iostream>
     
    int main()
    {
        Fct fct;
        auto wrapper = [&fct] {
            return fct.f();
        };
        std::cout << FindRoot(wrapper) << '\n';
    }

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Une fonction membre n'a pas une signature aussi simple. Ta fonction n'est pas void(*)(double) mais void(Fct::*)(double).
    Pour utiliser une fonction membre en callback il faut au moins l'instance de la classe que tu ne passes même pas.
    Le plus simple est sans doute d'utiliser std::function.
    Ou bien le foncteur et passer la callback via template.

    https://cpp.developpez.com/faq/cpp/?...qu-un-foncteur
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

Discussions similaires

  1. Passer une class comme argument de fonction
    Par Pelote2012 dans le forum Développement Web avec .NET
    Réponses: 2
    Dernier message: 07/08/2014, 12h03
  2. Réponses: 2
    Dernier message: 21/01/2014, 15h01
  3. Réponses: 3
    Dernier message: 05/11/2009, 10h28
  4. Réponses: 7
    Dernier message: 03/03/2008, 11h17
  5. [POO] passer une méthode en argument
    Par gorgonite dans le forum Langage
    Réponses: 4
    Dernier message: 09/11/2007, 18h56

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