Forum Programmation.c++ Une petite question d'héritage "sympathique"

Posté par  .
Étiquettes : aucune
0
3
mar.
2006
Voila je commence par le code d'exemple:

struct a
{
virtual int foo() =0;
virtual ~a(){}
};

struct b : public a
{
virtual int foo(int a) =0;
virtual ~b(){}
};

struct c :public b
{
int test()
{
return (this->foo() +
this->foo(2));
}
virtual ~c(){}
};

struct d :public c
{
virtual int foo() {return 1;}
virtual int foo(int a) {return a;}
virtual ~d(){}
};

int main()
{
d call;
return call.test();
}

Mon cher gcc4.1 tout neuf (ainsi que 3.2 et 3.4) me dit:
main2.cc: In member function 'int c::test()':
main2.cc:17: error: no matching function for call to 'c::foo()'
main2.cc:9: note: candidates are: virtual int b::foo(int)

Donc je me dis que c'est l'histoire du double space quelquechose... Je modifie c.
struct c :public b
{
int test()
{
return (this->a::foo() +
this->foo(2));
}
virtual ~c(){}
};
et la c'est mon cher ld des binutils.2.16 (et 2.11)
main2.cc:(.text._ZN1c4testEv[c::test()]+0xe): undefined reference to `a::foo()'
collect2: ld returned 1 exit status

Les seules façons de faire fonctionner sont soit:
-Dupliquer la déclaration de virtual int foo(void); dans b mais si j'ai une hiérarchie de classe c'est justement pour éviter de dupliquer
-Changer le nom d'une des deux fonctions foo foo(void) ou foo(int a) et forcément c'est gênant d'autant que vu que le prototype est différent ça devrait marcher.


Donc tout ça pour dire que je ne comprend pas l'origine du problème... le pourquoi. Des idées?
  • # valeur par defaut

    Posté par  . Évalué à 2.

    pourquoi ne pas faire une seule fonction avec valeur par defaut ?

    struct d :public c

    {
    virtual int foo(int a=1) {return a;}

    };
    • [^] # Re: valeur par defaut

      Posté par  . Évalué à 2.

      Car dans mon modèle objet réel les classes a b c d sont des couches de modélisations succécives de plus en plus complexes qui s'apellent les une les autres.

      Donc foo() et foo(valeur) ont deux comportements bien distincts.
  • # Masquage

    Posté par  (site web personnel) . Évalué à 4.

    La surcharge au travers d'un héritage revient en fait à un masquage.
    Il te faut réinjecter ta fonction à l'endroit de la surcharge (b) avec un :
    using a::foo;

    Quant à l'argument par défaut, à supposer que cela soit vraiment utilisable dans son problème, il est de bon ton de l'avoir dans toutes les déclarations. Ce qui, du coup, n'aide pas forcément.

    Autre solution : utiliser le Design Pattern "Template Method", que je préfère de loin aux appels explicites aux implémentations des fonctions définies dans les classes parentes.
    • [^] # Re: Masquage

      Posté par  . Évalué à 2.


      La surcharge au travers d'un héritage revient en fait à un masquage.


      Je ne savais pas ça, je croyais que le masquage n'intervenait que pour les prototypes identiques. Du coup ça marche mais ça ne me semble pas très beau.

      Merci
  • # focntion virtuelle

    Posté par  . Évalué à 2.

    Salut,

    il me semble que tu doivent implémenter la fonction foo dans la classe c.

    ( les fonctions foo de a et b étant virtuelle pure elles obligent les classes héritants d'elle a posséder cette fonction ( donc à la définir si elle est utilisée ou a la déclaréer virtuelle pure s'il la classe est trop généraliste qu'une implémentation de la fonction puissent exister).

    une erreur est effectivement générée si le compilateur remontent jusqu'à ces fonctions ( qui n'existent qu'en intention))
    • [^] # Re: fonction virtuelle

      Posté par  . Évalué à 2.

      Effectivement tu aurais raison si j'avais instancié un objet de classe c, car comme des fonctions ne sont pas définies, il est virtuel pur.
      Hors j'instencie un d qui définie foo et foo(int), donc elles existent. (enfin devraient...)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.