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 :

Templates, polymorphisme : sujet trop long pour ce titre


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut Templates, polymorphisme : sujet trop long pour ce titre
    Bonjour,

    Le sujet complet est :
    Un type paramètre d'une classe mère template doit-il matcher les besoins de la classe mère dans des méthodes qui sont redéfinies dans la classe fille ?

    Ce n'est peut-être pas plus clair, mais des détails suivent.

    J'ai un problème avec le code suivant :

    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
    #include <iostream>
     
    struct S
    {
      int a;
    };
     
    template <class T>
    class A
    {
    public:
      // on appelle f() de la classe instanciée
      void g( const T& t ) { f(t); }
     
    protected:
      virtual void f( const T& t ) { std::cout << t << std::endl; }
    };
     
    class B : public A<S>
    {
    protected:
      virtual void f( const S& t ) { std::cout << t.a << std::endl; }
    };
     
    int main()
    {
      S s;
      s.a = 24;
     
      B b;
      b.g(s);
     
      return 0;
    }
    Le problème est que ça ne veut pas compiler :
    Citation Envoyé par g++
    test_template_virtual.cpp: In member function `void A<T>::f(const T&) [with T = S]':
    test_template_virtual.cpp:12: instantiated from `void A<T>::g(const T&) [with T = S]'
    test_template_virtual.cpp:29: instantiated from here
    test_template_virtual.cpp:15: erreur: no match pour « operator<< » dans « std::cout << t »
    Si je comprends bien, g++ voudrait que operator<<() soit défini pour S sous prétexte que ça serait utilisé dans A::f(). Sauf que moi, ce que je vois, c'est que A::f() n'est jamais appelée, et que la version B::f() est appelée à la place. Ou alors il y a quelque chose que je n'ai pas vu. Alors qui a les plus mauvais yeux, g++ ou moi ?

    La version de g++ que j'utilise est la 3.4.4

    Merci pour votre aide.

  2. #2
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Aucun rapport avec le probleme mais:
    est mieux.

  3. #3
    Membre averti Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Points : 369
    Points
    369
    Par défaut
    Javais une erreur qui ressemblait a cela et cetais du aux constructeurs de copie. Essaie den ajouter a tes classes pour voir.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    Citation Envoyé par vdumont
    Javais une erreur qui ressemblait a cela et cetais du aux constructeurs de copie. Essaie den ajouter a tes classes pour voir.
    désolé, ça ne change rien :

    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
    struct S
    {
      S() {}
      S( const S& that ) {}
     
      int a;
    };
     
    template <typename T>
    class A
    {
    public:
      A() {}
      A( const A<T>& that ) {}
     
      void g( const T& t ) { f(t); }
     
    protected:
      virtual void f( const T& t ) { std::cout << t << std::endl; }
    };
     
    class B : public A<S>
    {
    public:
      B() {}
      B( const B& that ) {}
     
    protected:
      virtual void f( const S& t ) { std::cout << t.a << std::endl; }
    };

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    Bon, j'ai une première idée, c'est horrible mais ça compile. Attention attention, accrochez-vous :

    j'ai remplacé le corps de la fonction A::f() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <typename T>
    class A
    {
    public:
      A() {}
      A( const A<T>& that ) {}
     
      void g( const T& t ) { f(t); }
     
    protected:
      virtual void f( const T& t ) { std::cout << *(int*)&t << std::endl; }
    };
    Terrible, non ?

    En tout cas ça passe à la compilation et ça donne le résultat attendu à l'exécution.
    Par contre, je ne peux plus instancier A avec un type comme unsigned int...

    Si vous avez quoi que ce soit de plus respectable (le niveau est quand même très très bas), je suis preneur !

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Attention il ne faut pas confondre le comportement à la compilation et le comportement à l'execution.
    En l'occurence, tu as un problème de compilation que tu tentes d'expliquer par un comportement à l'execution. Le fait est que le compilo, lorsqu'il tente de compiler A<S>, ne peut pas savoir que A::f ne sera jamais appelé. Donc il te signale bien l'erreur.

    Mais je ne comprends pas ton design. Pourquoi ne pas faire une fonction f non virtuelle, et simplement définir un opérateur << pour S plutôt que de reléguer ce travail à B::f() ?

    Que sont les classes S, A et B ?

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    Alors dans le détail, ça devient un peu plus compliqué.

    Je résous des problèmes de sac à dos en variables binaires. Je manipule des problèmes mono et bi-objectifs. En gros, étant donné une variable du problème, elle m'apporte deux profits si je la met dans mon sac : p1 et p2 (d'où le bi-objectif). Je dois quelque fois combiner ces profits p = a * p1 + b * p2 (on tombe dans du mono objectif).

    L'idée du design est de ne pas avoir à réécrire plusieurs fois les algos de résolution selon que le problème à résoudre soit mono ou bi-objectif.

    Au final, la classe A est un algorithme de branch & bound très bien pour le mono objectif, T est le type du problème à résoudre, et B est un branch & bound qui hérite de A et qui redéfini quelques méthodes pour que ça marche bien.

    Si j'instancie A, alors T est mono-objectif, et le type du profit d'une variable est unsigned int. Si j'instancie B, alors T est bi-objectif, le type du profit est une structure avec deux champs : profit_1 et profit_2

    Voilà pour le détail. Je peux redéfinir les opérateurs attendus dans A sur les profits bi-objectifs, mais ça demande beaucoup de temps et ça peux m'amener des erreurs vraiment difficiles à retrouver (j'ai essayé...). Par exemple, je pourrais involontairement appliquer un algo strictement mono objectif à un problème bi-objectif, et là, bonjour la galère.

    En tout cas, merci pour votre aide.
    Je suis toujours preneur pour de nouvelles idées.

  8. #8
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Est-il nécessaire d'y avoir un polymorphisme d'inclusion au milieu ?
    Ne peux-tu te contenter simplement du polymorphisme paramétrique ?
    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
    struct S
    { int a; };
     
    template <typename T> struct serializer {
        static std::ostream & w(std::ostream&os, T const& v) 
        { return os << v; }
    };
     
    template <> struct serializer<S> {
        static std::ostream & w(std::ostream&os, S const& v) 
        { return os << v.a; }
    };
     
    template <typename T> class A
    {
    public:
      // on appelle f() de la classe instanciée
      void g( const T& t ) { f(t); }
     
    protected:
      void f( const T& t ) { serializer<T>::w(t); }
    };
     
    class B : public A<S>
    {
    protected:
        void whatever();
    };
     
    int main()
    {
        S s;
        s.a = 24;
     
        B b;
        b.g(s);
     
        return 0;
    }

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    Citation Envoyé par Luc Hermitte
    Ne peux-tu te contenter simplement du polymorphisme paramétrique ?
    Je crois en effet que c'était la meilleure approche. Je n'aurais pas l'occasion de tester car je vais devoir utiliser un autre algo.

    Merci à tous

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

Discussions similaires

  1. [AC-2000] Filtre trop long pour OpenReport
    Par B-CAB dans le forum VBA Access
    Réponses: 1
    Dernier message: 15/06/2010, 11h15
  2. Texte trop long pour afficher dans une combobox
    Par bavmorda1 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 12/02/2008, 14h42
  3. Temps de chargement trop long pour animation légère
    Par CharlyMops dans le forum Flash
    Réponses: 1
    Dernier message: 27/09/2006, 08h13
  4. Filtre trop long pour un état
    Par Miss Ti dans le forum Access
    Réponses: 3
    Dernier message: 08/08/2006, 18h54
  5. [TComboBox] Contenu trop long pour la zone d'affichage
    Par bebeours dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/09/2003, 17h21

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