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 :

Surcharge de fonction virtuelle pure


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut Surcharge de fonction virtuelle pure
    Bonjour à tous

    Aller, tout de suite, un petit ECM, pour présenter le problème, que je commente ensuite:

    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
    #include <iostream>
    #include <string>
    #include <vector>
    #include <math.h>
    #include <cassert>
     
    class FitFonction { /// classe abstraite
    public:
        /// Accesseurs
        std::vector<double> getParams() const { return _params; };
        int getNbParams() const { return _params.size(); };
        double get( int i ) const { return _params[i]; };
     
        /// Setters
        void setParams(const std::vector<double>& param){ assert(param.size()==_params.size()); _params=param; }; 
     
        /// Pour evaluer la fonction     
        virtual double eval(double x) const=0; // le "= 0" à la fin indique que c'est une fonction virtuelle pure 
        std::vector<double> eval(const std::vector<double>& x) const {  /// <----- ici je surcharge la fonction eval
        		std::vector<double> res(x.size(),0.0);
        		for (int i=0;i<x.size();i++) res[i]=eval(x[i]); 
        		return res; 
        };
     
    protected:
    		std::vector<double> _params;
    };
     
    class Gaussienne : public FitFonction { /// 1 Gaussienne = 3 paramètres
    public:
          Gaussienne(double h, double c, double e){ _params.resize(3);
    				_params[0]=h; _params[1]=c; _params[2]=e; };
     
          double eval(double x) const {return _params[0]*exp(pow((x-_params[1])/_params[2],2.0));};
    };
     
    int main( int argc, char* argv[] ){
    		Gaussienne fct(1.3,2.0,5.3);
    		std::vector<double> xx(7,0.2),yy(7);
    		//yy=fct.eval(xx);
    		std::cout << "Hello World !" << std::endl;
    }
    Je créé une classe FitFonction, qui va donc regrouper plusieurs type de fonction mathématique de base.
    Ces fonctions de bases dépendent de paramètres (que je met en attribut de classe).
    Quelquesoit la fonction mathématique, je vais avoir envie de l'évaluer, en un point ou en un vecteur de points.
    Je créer donc la méthode "virtual double eval(double)" en virtuelle pure, car elle dépendra de ma fonction mathématique (dans l'exemple j'ai pris une gaussienne, mais on pourrait très bien y ajouter des fonctions affines, logarithmiques, etc...).
    Je définis ensuite ma méthode d'évaluation dans ma classe fille Gaussienne.
    Jusque là tout va bien.

    Maintenant, je vais souvent avoir besoin d'évaluer, non pas un seul point, mais un vecteur de point.
    Je veux donc surcharger ma fonction eval: "std::vector<double> eval( const std::vector<double>& )".
    Et c'est ce que j'essaie de faire ligne 19 à 23, mais il semble que ca ne marche pas ...
    Dans le main, je veux pouvoir décommenter la ligne 40. Si je le fais je me fais insulter par le compilo :
    test.cxx:91:15: error: no viable conversion from 'std::vector<double>' to 'double'
    yy=fct.eval(xx);
    ^~
    Merci pour votre aide.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Il est possible que la redéfinition d'une des fonctions cache ses surcharges.
    Peut-être qu'un using dans la classe dérivée pourrait aider?
    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
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 502
    Par défaut
    Comme je pense que la seconde méthode eval n'a strictement rien à faire dans la classe, je serai partisan d'une fonction libre, d'une lambda expression ou d'une méthode statique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::transform(v.begin(), v.end(), v.begin(),[](double d) {fct.eval(d);});

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Une autre version, respectant le NVI (non virtual interface) : Tu rends tes deux fonctions eval non virtuelles, et tu les fait utiliser une fonction privée virtuelle pure doEval.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Alors pour répondre à vos propositions dans l'ordre :

    @Médinoc: J'ai essayé plusieurs choses à base de "using" dans la classe Gaussienne, en vain.
    Cela dit en lui disant explicitement de reprendre la fonction de la classe mère ca se passe bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Gaussienne : public FitFonction {
    public:
    // ...
    std::vector<double> eval(const std::vector<double>& x) const { return FitFonction::eval(x); };
    };
    @bacelar : Effectivement, on pourrait externaliser la méthode. J'ai donc penser à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::vector<double> feval(const FitFonction& fct, const std::vector<double>& x){
    		std::vector<double> y(x);
    		//std::transform(y.begin(), y.end(), y.begin(),[](double d) {fct.eval(d);});
    		//std::transform(y.begin(), y.end(), y.begin(), fct.eval );
    		for (int i=0;i<y.size();i++) y[i]=fct.eval(x[i]); 	
    		return y;
    }
    J'ai procédé avec un "for" car les essais commentés avec std::tranform ne compile pas...

    @JolyLoic : Pas mal cette idée, en créant juste une indirection, on peut ainsi s'en sortir :

    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
    class FitFonction { /// classe abstraite
    public:
        /// Accesseurs
        std::vector<double> getParams() const { return _params; };
        int getNbParams() const { return _params.size(); };
        double get( int i ) const { return _params[i]; };
     
        /// Setters
        void setParams(const std::vector<double>& param){ assert(param.size()==_params.size()); _params=param; }; 
     
        /// Pour evaluer la fonction     
        double eval(double x) const { return doEval(x);  }
        std::vector<double> eval(const std::vector<double>& x) const {
        		std::vector<double> res(x.size(),0.0);
        		for (int i=0;i<x.size();i++) res[i]=doEval(x[i]); 
        		return res; 
        };
    protected:
    		virtual double doEval(double x) const=0;
     
    		std::vector<double> _params;
    };
     
    class Gaussienne : public FitFonction { /// 1 Gaussienne = 3 paramètres
    public:
    		Gaussienne(double h, double c, double e){ _params.resize(3);
    				_params[0]=h; _params[1]=c; _params[2]=e; };
     
    protected :
    		double doEval(double x) const {return _params[0]*exp(pow((x-_params[1])/_params[2],2.0));};
    };
    Merci à vous pour vos solutions.
    Si vous voulez réagir je laisse le topic quelque jours avant de le passer en résolu.

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

Discussions similaires

  1. Réponses: 16
    Dernier message: 21/05/2007, 01h04
  2. Réponses: 2
    Dernier message: 30/01/2007, 11h44
  3. surcharge de fonction virtuelle et VC++6
    Par grodwar dans le forum MFC
    Réponses: 28
    Dernier message: 21/06/2006, 10h19
  4. Réponses: 2
    Dernier message: 05/03/2006, 19h29
  5. Compilation avec des fonctions virtuel pure
    Par vanitom dans le forum C++
    Réponses: 4
    Dernier message: 16/12/2005, 14h37

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