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 :

Templates, virtuel, casse-tête


Sujet :

Langage C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 47
    Par défaut Templates, virtuel, casse-tête
    Bonjour à tous,

    Voici un bref extrait de code pour vous exposer mon problème:

    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
    template <class T> class O {
      public:
        virtual T hi() = 0;
    };
     
    template <class T> class Ab : public O<T> {
      public:
        virtual T hi() {
          return 1;
        }
    };
     
    template <class T> class B : public Ab<T> {
      public:
     
        T aie() {
          return hi(); /* PROBLEME */
        }
    };
     
    template <class T> class C : public B<T> {
      public:
        virtual T hi() {
          return 2;
        }
    };
     
    #include <iostream>
    using namespace std;
     
    int main() {
      C<int> my;
      cout << my.aie() << endl;
     
      return 0;
    }
    Il se situe dans la classe B, je voudrais que dans la fonction "aie" l'appel à "hi" renvoie 2 (vu la définition dans C), et évidemment si "hi" n'est pas défini dans C qu'il renvoie 1 (vu la définition dans Ab).

    Le problème est qu'en l'état g++ me donne l'erreur suivante :

    a.cc: In member function ‘T B<T>::aie()’:
    a.cc:17: error: there are no arguments to ‘hi’ that depend on a template parameter, so a declaration of ‘hi’ must be available
    a.cc:17: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

    Si je modifie return hi(); dans B par return Ab<T>::hi(); il me retourne 1 au lieu de 2.

    Si je modifie return hi(); dans B par return O<T>::hi(); il me dit que la référence est indéfinie.

    Comment puis-je appeler hi() dans B pour qu'il me retourne 2 et avoir le comportement voulu ?

    Merci d'avance,

    Benjamin

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 47
    Par défaut
    C'est bon, un ami que j'ai envoyé sur le topic m'a donné la réponse. Il suffit de faire un appel this->hi();

    Au cas où ça peut servir à quelqu'un .

  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    C'est un des rares cas où this est nécessaire pour accéder aux membres d'une classe. Cela est du à la dépendance du nom (Base<T> est dépendante de T).
    De la même façon que si tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <class T> class O {
      public:
          typedef T type;
    Ensuite tu dois faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T> class B : public Ab<T> {
      public:
    
        T aie() {
           typename Ab<T>::type t;

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    A noter qu'on peut aussi utiliser l'opérateur de résolution de portée, ou un using pour résoudre ce problème. Le choix d'une technique ou l'autre dépend de problème exact et du résultat voulu. Passé par this permet l'utilisation du polymorphisme, les deux autres non (mais on a pas forcément besoin de lui), la dernière forme à l'avantage de rendre les choses plus lisible.

    Cf FaQ template de comeau pour une explication plus longue et complète.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Citation Envoyé par Flob90 Voir le message
    A noter qu'on peut aussi utiliser l'opérateur de résolution de portée
    Je comprends pas. Ab::hi fera une résolution statique de l'appel. Qu'entends-tu par opérateur de résolution de portée ?

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Oui ca sera un appel statique (ce que j'ai voulu dire pas "ne permet pas l'utilisation du polymorphisme"), ca ne correspond pas au problème exact de l'OP. Je ne faisais que préciser pour le problème dans le cas plus général.

    Le problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template<class T>
    struct A
    { void foo(){} };
     
    template<class T>
    struct B : A<T>
    {
      void bar()
      { foo(); } //erreur
    };
    Les solutions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    this->foo();
     
    A<T>::foo();
     
    using A<T>::foo; //Dans le corps classe, sinon ca n'a aucun interet
    La première est celle que tu as donné et est la solution pour benlaug, la second peut convenir si une résolution statique suffit.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Oui ca sera un appel statique (ce que j'ai voulu dire pas "ne permet pas l'utilisation du polymorphisme"), ca ne correspond pas au problème exact de l'OP. Je ne faisais que préciser pour le problème dans le cas plus général.
    ma mémoire de poisson rouge avait oublié le début de ta phrase en lisant la fin

    J'ai pas trop le courage de regarder dans la norme à cette heure-ci, mais j'ai une résolution dynamique en utilisant using Ab<T>::hi; (soit la troisième solution).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <class T> class B : public Ab<T> {
      public:
     
        using Ab<T>::hi;
     
        T aie() {
          return hi(); // appelle la version la + dérivée
        }
    };

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    la second peut convenir si une résolution statique suffit.
    Et avec le pattern NVI (qu'on ne vantera jamais assez) même plus besoin de se poser la question sur quand se fait la résolution. Les trois comportements sont identiques
    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
    template<class T>
    struct A
    { void foo(){do_foo();}
    private:
    virtual void do_foo()=0;
    };
     
    template<class T>
    struct B : A<T>
    {
        using A<T>::foo;
      void bar()
      {
          A<T>::foo();
          this->foo();
          foo();
     
      }
     
      private:
      virtual void do_foo(){}
    };

  9. #9
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Ha oui en effet, j'avais pas vu ca comme ca. Pour la norme c'est section 7.3.3 paragraphe 16 (n3242), les fonctions "réintroduitent" par un using sont traitées comme des fonctions appartenants à la classe. (Et du coup elle est traitée comme n'importe quel autre fonction virtuelle)

    Du coup si il faut faire plusieurs fois this->foo(), utilisé un using est assez adapté.

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

Discussions similaires

  1. [Tableaux] Casse têtes de boucles
    Par Anduriel dans le forum Langage
    Réponses: 5
    Dernier message: 28/06/2006, 00h24
  2. Classe, pile, pointeurs et casse-tête!
    Par zazaraignée dans le forum Langage
    Réponses: 6
    Dernier message: 26/09/2005, 16h57
  3. casse-tête excel
    Par gregius dans le forum Access
    Réponses: 2
    Dernier message: 21/09/2005, 16h38
  4. Fonction template virtuelle... comment l'éviter ?
    Par :Bronsky: dans le forum Langage
    Réponses: 12
    Dernier message: 07/06/2005, 14h21

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