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 :

Interface et template


Sujet :

Langage C++

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2014
    Messages : 9
    Points : 1
    Points
    1
    Par défaut Interface et template
    Bonjour,
    Je travaille actuellement sur une application de traitement d'images et je rencontre un petit souci.
    L'architecture se compose en 3 classes: la classe virtuelle IimageManager, et deux classes qui implémentent l'interfaces ImageManager8 et ImageManager16.
    Voici les 3 classes:
    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
    <typename T1>
    class IimageManager{
    int getMax(T1 matrice);
    };
     
     
    class ImageManager8: public IimageManager<QImage>{
    ...
    ImageManager8* ImageManager8::getInstance(){...}
    int ImageManager8::getMax(QImage matrice){...}
    };
     
     
    class ImageManager16: public IimageManager<unsigned short*>{
    ...
    ImageManager16* ImageManager16::getInstance(){...}
    int ImageManager16::getMax(unsigned short* matrice){...}
    };
    Jusque là je n'ai pas de problème de compilation. Le soucis viens dans le main au niveau de l'instanciation.
    J'aurai souhaité faire quelque chose de générique du genre.

    IimageManager* monManager;
    (format==8)?monManager=ImageManager8::getInstance():monManager=ImageManager16::getInstance();

    Cependant lorsque je fais quelque chose de ce type j'ai une erreur de compilation car je dois préciser le type utilisé pour pour IimageManager. Mais au moment ou je déclare l'attribut monManager, je ne connais pas le type que je veux utiliser (QImage ou unsigned short*).
    Du coup je fais appel à votre aide...

    Merci

  2. #2
    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 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Salut,

    l'erreur est plutôt explicite.
    T'es-tu déjà venu à l'esprit de faire un std::vector* pVec; ?
    Le compilo t'insultera tout autant. Un template est défini pour un type donné.

    La seule alternative c'est de faire une classe parente qui sert d'interface.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class A { virtual void Do() {} };
    template< class T >
    class B : A {};
     
    A* pA;
    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.

  3. #3
    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
    Toi, tu as fait du java, non?

    En C++, une template de classe n'est pas une classe.
    C'est un modèle, que le compilateur utilise pour créer des classes qui se ressemblent.

    en l'occurence, voici comment ton code est traité par le compilateur:
    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 T1>
    class IimageManager{
        int getMax(T1 matrice);
    };
    tiens une template de class nommé IimageManager
    Ok, je note pour plus tard...
    */
     
    /*tiens, je dois traiter ca: class ImageManager8: public IimageManager<QImage>
    ah, mais j'ai pas encore cette instance de IimageManager
    bon, j'ai bien un modèle, allons y:
    */
    class IimageManager<QImage>{
        int getMax(QImage matrice);
    };
     
    /* reprenons... j'en étais où, déjà? */
    class ImageManager8: public IimageManager<QImage>{
    ...
    ImageManager8* ImageManager8::getInstance(){...}
    int ImageManager8::getMax(QImage matrice){...}
    };
     
     
    /* et ca recommence, encore un template que je n'ai pas traité
    bon, j'ai toujours le modèle, allons y:
    */
    class IimageManager<unsigned short*>{
        int getMax(unsigned short* matrice);
    };
     
    class ImageManager16: public IimageManager<unsigned short*>{
    ...
    ImageManager16* ImageManager16::getInstance(){...}
    int ImageManager16::getMax(unsigned short* matrice){...}
    };
    /*
    ouf, j'y suis arrivé
    */
    Ton problème, c'est bien que IimageManager<QImage> et IimageManager<unsigned short*> sont deux classes différentes, et sans lien.
    Il leur faut une classe de base.
    à toi de trouver un dénominateur commun.

    D'après ton problème, c'est que tu essaie de détemplater une classe qui ne devrait pas forcément.
    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

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Les classes dérivant d'un même template mais avec des paramètres de template différent ne partage aucun lien de parenté.
    Le plus simple est d'encapsuler ce singleton dans un Singleton à vous qui fera le switch en interne.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2014
    Messages : 9
    Points : 1
    Points
    1
    Par défaut
    Merci beaucoup pour vos réponses.
    Oui en effet j'ai fais pas mal de java...
    En fait dans mon idée, la classe iImageManager était ma classe modele avec des méthodes virtuelles pures utilisant des types templates.
    Mais du coup comment puis-je créer une classe mère en utilisant des templates.

    Je suis un peu perdu la...

  6. #6
    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 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    template et virtual ne sont pas compatible
    le "truc" qui s'en rapprocherait c'est du CRTP
    mais je pense plutôt que tu essayes de mimer un comportement JAVA, qui est donc mauvais
    en énonçant clairement ton problème nous pourrons t'indiquer comment le résoudre
    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.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Les templates C++ ne sont pas des "génériques" JAVA.

    Compile time VS Runtime

    On vous propose l'héritage : voir le code de Bousk.
    Moi, je propose l'encapsulation dans un autre Singleton.

    Le choix, c'est fonction de la manière dont tu veux te servir de la chose.

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2014
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2014
    Messages : 9
    Points : 1
    Points
    1
    Par défaut
    Tout d'accord merci pour vos réponses.
    En fait mon problème est d'utiliser le polymorphisme avec des templates mais appartement ce n'est pas possible en utilisant des méthodes virtuelles pures.
    Je ne vois pas trop comment utiliser un singleton. Auriez vous un exemple?

    Merci

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Je ne vois pas trop comment utiliser un singleton. Auriez vous un exemple?

    Le code que vous avez posté en contient déjà 2.
    http://fr.wikipedia.org/wiki/Singlet...de_conception)

  10. #10
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Le polymorphisme, c'est "j'appelle l'objet sans savoir de quel sous-type il est, et les appels sont corrects car je n'ai pas besoin de cet information (le sous-type) pour que le traitement correct soit mis en oeuvre". Cette substituabilité repose sur le fait que tous les objets ont la même interface.
    Pose toi simplement cette question: en admettant que tu aies un pointeur de type IimageManager*, comment ferais tu pour appeler la fonction int getMax(T1 matrice); sans connaître le type effectif de ton manager, alors que le type de l'argument matrice diffère selon le type effectif en question?

    (PS: en java le type erasure au runtime est un détail d'implémentation, et un code qui prétend faire du polymorphisme avec des generics sans avoir défini une interface commune indépendante du ou des paramètre(s) de type ne passera pas la compilation, sauf à faire des hacks tordu qui donnent un code boiteux)

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    Heu, je vois pas trop le rapport entre le type erasure JAVA et le problème ici.

    Même en JAVA, une interface générique n'est pas instanciable, enfin je crois.

    Le problème, c'est la définition de l'API :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int getMax(T1 matrice);
    C'est pas bon car T1 n'est pas connu et je ne pense pas que c'est le but recherché.

    Il faut réfléchir à l'API que vous voulez offrir au code client :
    Un truc de normand, c'est de fournir les 2 avec un choix au compile time :

    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
     
    #if FORMAT == 8
       typedef Image QImage;
    #else
       typedef Image unsigned short*;
    #endif //FORMAT == 8
     
    class ImageManager
    {
        int getMax(Image matrice)
       {
    #if FORMAT == 8
            return ImageManager8::getInstance().getMax(matrice);
    #else
            return ImageManager16::getInstance().getMax(matrice);
    #endif //FORMAT == 8
       }
    }

  12. #12
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    donc la question se résume à:
    Develop-peur, veux-tu que le choix du type de manager soit fait:
    • à la compilation: dans ce cas laisse tomber ton pointeur, qui ne sert à rien, et utilises ton template directement (vie un typedef éventuellement si tu ne veux pas qu'on voie l'aspect template dans le code client)
    • au runtime: dans ce cas il faut que tu définisse une API commune aux deux types de managers. Ta classe de base ne doit PAS être un template. Si d'aventure tu avais absolument besoin d'utiliser de la généricité, tu dois définir une classe template qui dérive de ta classe de base non template (mais ce n'est pas une obligation, ne le fais que si ça résoud un problème que le polymorphisme par dérivation ne permet pas de résoudre).

  13. #13
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par bacelar Voir le message
    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
     
    #if FORMAT == 8
       typedef Image QImage;
    #else
       typedef Image unsigned short*;
    #endif //FORMAT == 8
     
    class ImageManager
    {
        int getMax(Image matrice)
       {
    #if FORMAT == 8
            return ImageManager8::getInstance().getMax(matrice);
    #else
            return ImageManager16::getInstance().getMax(matrice);
    #endif //FORMAT == 8
       }
    }
    Personellement j'évite au maximum la compilation conditionnelle, je trouve que ça obscurcit le code. Ici, la programmation générique fera ça très bien...

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 073
    Points : 12 119
    Points
    12 119
    Par défaut
    S'il à pas besoin de polymorphisme mais de codes portable, ça sert à rien de monter une Ariane5.
    Avec des singletons, le polymorphisme au runtime, c'est pas très "naturel".

    Bon, on tourne en rond. Avant de régler le problème, il faut que le PO ait conçu une API pour son code client.

  15. #15
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Une Ariane5? Deux typedefs pour réaliser un template? Moué...
    Par ailleurs, sa formulation tend à indiquer une volonté de choix au runtime...ce que je souhaitais confirmer.
    Suggestion: avoir les deux fonctions dans une même façade et utiliser la surcharge au lieu du polymorphisme. Et utiliser la composition, si le managerr doit être gardé toute la vie de l'application.
    Par ailleurs, le DP Singleton est très déconseillé de nos jours...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class ImageManagerAdapter{
    private:
      ImageManager16 man16;
      ImageManager8 man8;
    public:
      int getMax(const QImage &matrice){
        return man16.getMax(matrice);
     };
     int getMax(unsigned short *matrice){
        return man8.getMax(matrice);
     };
    };
    Concernant l'implémentation des deux image managers, le template devient peut-être inutile (s'il avait été uniquement mis en jeu en croyant profiter d'un effet "classe de base"), mais on n'en sait pas assez pour parler...
    Ce cas de figure effectue le choix à la compilation. En fonction des contraintes exactes qu'on ne connaît pas, on peut peut-être aussi s'en servir au runtime...

  16. #16
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Bonjour, peut être simplement utiliser une spécialisation ?
    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 Format8Tag {};
    struct Format16Tag {};
    //------------------------------------------------------------------------------
    template<class Tag>
    struct MatriceType
    {};
    //------------------------------------------------------------------------------
    template<>
    struct MatriceType<Format8Tag>
    { using type = QImage; };
    //------------------------------------------------------------------------------
    template<>
    struct MatriceType<Format16Tag>
    { using type = unsigned short*; };
    //------------------------------------------------------------------------------
    template<typename Tag>
    struct ImageManager
    {
        int getMax(const typename MatriceType<Tag>::type matrice) const;
        ImageManager* getInstance() const;
    };

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Là par contre, je rejoindrai bacelar: je soupçonne le besoin du PO d'être plus simple que ça...

  18. #18
    Invité
    Invité(e)
    Par défaut
    Ce que j'aime bien faire (et d'ailleurs je trouve que le c++ est bien grâce à ça), c'est, créer une interface commune, et, redéfinir l'opérateur d'affectation et le constructeur de copie pour convertir un objet de type X<T> en un objet de type Y<T>.

    En java il y a moyen aussi mais il me semble que ce n'est pas aussi facile, la surcharge d'opérateur n'existe pas et lors de la déclaration d'une collection, il n'y a rien qui correspond vraiment à un boost variant, il y a le mot clé extends pour les template mais, celui ci ne permet que de pouvoir initialiser les contenaire avec plusieurs type différent, mais, pas de pouvoir stocker des objets de plusieurs types différents.

    Tandis que en c++ il y a moyen de se passer d'une interface. (Ou tout du moins, la cacher je dirais plutôt)

  19. #19
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Cacher une interface? Personnellement, quand j'en définis une, c'est pour qu'on la voie. Dans l'idéal même pour qu'on ne voie que ça!
    Manipuler un sac de porridge au contenu non-identifié est peut-être nécessaire pour répondre à certains corner cases, mais quand je conçois je fuis ce genre de cas comme la peste...
    Pour la petite histoire, en java, on peut utiliser le mot clef extends pour pour définir un container dans lesquels on peut ajouter ou récupérer des objets de types variés, pourvu qu'ils soient tous dérivés du même supertype (ou implémentent tous le même interface). Mais là, on s'écarte du sujet...

  20. #20
    Invité
    Invité(e)
    Par défaut
    Oui donc en java tu es obligé de dériver d'une classe commune ou bien d'implémenter une interface commune pour stocker des éléments de différent types dans une collection et leur appliquer des comportements différents. (Tu dois donc faire plusieurs collections pour toutes les interfaces et utiliser la bonne en dépendant du type de comportement que tu veux appliquer)

    En C++ ce n'est pas nécessaire tu peux stocker tous les éléments dans une collection avec un variant, et faire une interface par comportement en appliquant le variant sur l'interface désirée en fonction du comportement que tu veux appliquer, je trouve ça beaucoup plus pratique.

Discussions similaires

  1. template, "interface", implementation
    Par line86 dans le forum Langage
    Réponses: 8
    Dernier message: 03/04/2009, 20h52
  2. Moteur de template ou interface personnalisable.
    Par SPKlls dans le forum Général Conception Web
    Réponses: 0
    Dernier message: 27/01/2009, 19h53
  3. [VB6] [Interface] ComboBox à plusieurs colonnes
    Par mtl dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 30/03/2004, 17h35
  4. [VB6] [Interface] Horloge 7 segments
    Par selenay dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 07/10/2002, 16h15
  5. interface utilisateur avec OpenGL
    Par demis20 dans le forum OpenGL
    Réponses: 6
    Dernier message: 03/10/2002, 12h27

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