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 :

Foncteur + Template + héritage


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 33
    Points : 27
    Points
    27
    Par défaut Foncteur + Template + héritage
    Bonjour tout le monde,

    Voici mon problème : j'ai une classe A qui définie une méthode MA faisant appel a une méthode virtuelle pure MVP et la classe B qui hérite de A et qui donc implémente la MVP : précision les classe A et B sont des classes Template.
    Jusque la pas de problème, ça marche.

    Maintenant, j'ai besoin de changer le comportement de MVP : j'ai ajouté donc plusieurs MVP définies dans A et implémentées dans B. En fonction d'un paramètre de MA je choisi de faire telle ou telle MVP : j'ai donc un gros switch en plein milieu de la fonction MA pour choisir la bonne MVP : la solution les foncteurs bien sur !

    Sauf que je n'y arrive pas du tout : mon gros problème c'est que je n'arrive pas a déclarer un foncteur vers une MVP template de la classe A, faut il le faire "a l’intérieur" de la classe, ou l’extérieur ?

    Voila ou j'en suis en plus simplifié :

    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
     
    template <typename T>
    class A
    {
    public:
     
        typedef T (A::*InterpolationFunc)(float, float, float); // declaration qui ne marche pas
     
        void MA(InterpoaltionType type)
        {
            InterpolationFunc interpFunc = selectInterpoaltion(type); // choix de la bonne fonction d'interpolation
     
            // appel de interpFunc dans une boucle
        }
     
        InterpolationFunc selectInterpoaltion(type)
       {
            switch(type)
            {
             case 1 : return &A::interpolation1;
             case 2 : return &A::interpolation2;
             ...
             case N : return &A::interpolationN;
            }
       }
     
        virtual void T interpolation1(float, float, float) = 0;
        virtual void T interpolation2(float, float, float) = 0;
        ...
        virtual void T interpolationN(float, float, float) = 0;
    };
     
    template <typename T>
    class B : public A<T>
    {
        void T interpolation1(float, float, float) { ... }
        void T interpolation2(float, float, float) { ... }
        ...
        void T interpolationN(float, float, float) { ... }
    };
    J’espère que j'ai était assez clair,
    Merci d'avance pour le coup de main !

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Peut-être comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef T (A<T>::*InterpolationFunc)(float, float, float);
    Au passage, les templates mis à part, ton problème ressemble à un pattern Stratégie ;aussi il serait peut-être judicieux de distribuer tes interpolation[1..N] dans N classes au lieu de N méthodes.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Points : 158
    Points
    158
    Par défaut
    Ton switch est un cas typique se prêtant bien à l'héritage et la virtualité :
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #include <iostream>
     
    using namespace std;
     
    template<typename T>
    struct InterpolationFunc
    {
        virtual T operator()(float, float, float) = 0;
    };
     
    template<typename T>
    struct InterpolationFunc1 : public InterpolationFunc<T>
    {
        virtual T operator()(float, float, float){ cout << "interpolation 1" << endl; } //warning car manque le return
    };
     
    template<typename T>
    struct InterpolationFunc2 : public InterpolationFunc<T>
    {
        virtual T operator()(float, float, float){ cout << "interpolation 2" << endl; }
    };
     
    template<typename T>
    struct InterpolationFunc3 : public InterpolationFunc<T>
    {
        virtual T operator()(float, float, float){ cout << "interpolation 3" << endl; }
    };
     
    class A
    {
        public:
            template<typename T>
            void MA(InterpolationFunc<T>& func)
            {
                T ret = func(1.0, 1.0, 1.0);
                /* other processing */
            }
    };
     
     int main(int argc, char** argv)
     {
        A a;
        InterpolationFunc1<int> func1;
        InterpolationFunc2<int> func2;
        InterpolationFunc3<int> func3;
     
        a.MA(func1);
        a.MA(func2);
        a.MA(func3);
     
        return 0;
     }

  4. #4
    Invité
    Invité(e)
    Par défaut
    typedef T (A::*InterpolationFunc)(float, float, float); // declaration qui ne marche pas
    pour moi c'est legit.

    virtual void T???

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    As tout hasard, tu as vérifié la juste présence de "typename" aux bons endroits?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 33
    Points : 27
    Points
    27
    Par défaut
    Cela marche bien ; en fait, j'ai le code du fichier template dans un .cpp séparé (inclut à la fin du .h) et donc il fallait adapter l’entête de la fonction selectInterpoaltion :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    //.h
    typedef T (A<T>::*InterpolationFunc)(float, float, float) const;
     
    InterpolationFunc selectInterpoaltion(InterpolationType type) const;
     
    //.cpp
    template<typename T>
    typename A<T>::InterpolationFunc
    A<T>::selectInterpoaltion(InterpolationType type) const
    {
    // code ...
    }
    virtual void T???
    Oui petite faute de frappe, il fallait comprendre virtual T

    Merci à tous en tout cas,

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Choisis une autre extension pour l'implémentation des templates.
    j'utilise personnellement .tpp voire .t.h ou .t.hpp

    Cela permet de ne pas se tromper en compilant, ni de confondre avec un en-tête réel ou une unité de compilation
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 33
    Points : 27
    Points
    27
    Par défaut
    Bien vu pour le typename, tu m'as devancé ...
    Par contre c'est le compilateur qui m'as dit de mettre un typename mais je comprends pas pourquoi même si cela marche : une explication ?

    Sinon, pour les extensions je fais tpl.h et tpl.cpp

  9. #9
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Le typename sert à dire au compilateur "je sais que le truc nommé machin dans cette classe est un type".
    C'est utile et nécessaire à cause du mécanisme de spécialisation de template.

    Pour spécialiser une classe (ou structure) template, il faut intégralement la définir.
    Rien n'empeche de faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <typename T> struct base{
    typedef T value_t;
    T value;
    base(const T& v):value(v){}
    };
     
    template<>
    struct base<void>{
    int value_t;
    base():value_t(42){}
    };
    Auquel cas, selon que T!=void ou non, base<T>::value_t est un type ou une variable.

    Suppose le code template <typename T> base<T>::value_t f(int);.
    Le compilateur ne le sait pas encore si T est void ou non, et donc si value_t est ou non un type.
    Du coup tu dois écrire template <typename T> typename base<T>::value_t f(int);.

    Pour l'extension, aucun fichier utilisé dans un #include ne devrait être finir par .cpp. Cela évite de futurs problèmes, et améliore la lecture du code pour un nouvel utilisateur.
    Ca permet de compiler avec g++ *.cpp
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  10. #10
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Ca permet de compiler avec g++ *.cpp
    À éviter ! Après, tu es obligé de recompiler tout le projet même si tu n'as modifié qu'un fichier. Et la compilation peut-être longue…

    Mais bon pour les petits projets pourquoi pas…

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Bien sûr que c'est à éviter.

    Mais on ne nomme pas roue un volant, même si les deux sont ronds... de même, .cpp est l'extension exclusive des implémentations, pas des en-têtes.

    Un #include "truc.cpp" est une abbération.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Citation Envoyé par leternel Voir le message
    Bien sûr que c'est à éviter.
    Alors pourquoi le donner en exemple ? La raison que tu viens de donner est quand même plus pertinente.

    Enfin soit, c'était juste pour préciser…

  13. #13
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Pourquoi? Parce que c'est assez courant quand on veut juste installer à partir des sources, sans forcément avoir envie de développer avec.

    Mais je reconnais que ce n'est pas du tout la meilleure raison.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/01/2008, 23h39
  2. Template + Héritage
    Par richard_sraing dans le forum Langage
    Réponses: 4
    Dernier message: 30/07/2007, 13h34
  3. Templates + Héritage + Allocation dynamique
    Par bouba dans le forum C++
    Réponses: 2
    Dernier message: 26/04/2007, 17h56
  4. Template, héritage multiple et redéfinition
    Par Paul Atreide dans le forum Langage
    Réponses: 5
    Dernier message: 31/10/2006, 14h00
  5. template, héritage et std:deque
    Par jmtrivial dans le forum Langage
    Réponses: 7
    Dernier message: 27/09/2006, 15h08

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