Forum Programmation.c++ Héritage et constructeurs

Posté par  .
Étiquettes : aucune
0
10
août
2004
Salut les devs,

J'ai une question concernant l'héritage en C++.
Est-il possible d'"hériter" des constructeurs de la classe A dont hérite une certaine classe B?

Je m'explique...
Soit une classe A avec 5 constructeurs par paramètres.
Je voudrais que la classe B puisse avoir ces mêmes 5 constructeurs par paramètres sans avoir à ré-emballer/ré-implémenter ces 5 constructeurs.
(Note : marche aussi avec X constructeurs, X> >1 ;) )

Existe-t-il un moyen simple qui permette de faire cela automagiquement (en C++ standard, parce que je crois avoir vu un truc avec boost (InPlaceFactory?) qui permett(r)ait de le faire) ?

Suggestions, idées ou autres sont les bienvenues.
  • # Ben oui, c'est le principe de la prog objet quand même ...

    Posté par  . Évalué à 1.


    class A
    {
    private:
    int a, b, c;
    public:
    A(int _a, int _b, int _c) : a(_a), b(_b), c(_c) {};
    A(int bidule, int _a, int _b, int _c) {
    a = bidule * _a;
    b = bidule * _b;
    c = bidule * _c;
    };
    }

    class B : public A
    {
    }

    int main(int argc, char* argv[])
    {
    B objB(2, 3, 4, 5);

    return 0;
    }
    • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

      Posté par  . Évalué à 1.

      Même si la classe est templatisée ?
      Désolé si j'ai un peu trop simplifié... :/

      Le problème c'est que j'utilise des std::vector<T*>
      aggrégés dans un DataVector (pour gérer certains aspects
      de persistance des données).
      Et pour ces mêmes aspects de persistance de données, il est d'usage
      de définir pour chaque classe Bidule, une classe BiduleContainer
      qui hérite de DataVector.

      Les éléments de DataVector sont alloués dynamiquement, et c'est donc DataVector qui en a la propriété.

      Bon je vais pas me répandre dans les détails techniques (que je ne maitrise pas suffisamment d'ailleurs), mais voilà en gros comment ca se goupille :

      template<typename T>
      class DataVector
      {
      private:
      OwnershipPolicy m_ownPolicy;
      typedef std::vector<T*> PtrVector;

      PtrVector m_pCont;

      public:
      DataVector(OwnershipPolicy ownPolicy = OWN_ELEMENTS);
      DataVector( InputIerator first, InputIterator last, OwnershipPolicy = VIEW_ELEMENTS );
      DataVector( ... );
      /* ...*/
      }
      et donc ensuite on peut definir des classes,
      class BiduleContainer : public DataVector { ... }

      et c'est donc à ce moment là que je voudrais pouvoir réutiliser les constructeurs par paramètres du template DataVector (principalement le constructeur qui permet de ne pas effacer les objets contenus car ils sont contenus par un autre conteneur qui lui a les droits de propriété.

      Est-ce que c'est plus clair ?
      Parce que bien entendu, même si je ne suis pas un programmeur C++ de haut niveau (cf [1]) j'ai quand même quelques bases :P

      Mon erreur (ou en tout cas une) c'est que je surchargeais l'operateur de construction par défaut ( ie: (void) sans définir d'Ownership par défaut) de ma class BiduleContainer.
      Mais le fait que je ne pas construire de BiduleContainer en utilisant la copie par itérateurs.

      Voilà voilà...

      [1] : https://linuxfr.org/~linuxfan/14787.html(...)
      • [^] # Détail qui a son importance :

        Posté par  . Évalué à 1.

        J'ai oublié un détail qui a son importance :
        tous les constructeurs de DataVector sont définis avec le mot clé explicit...
      • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

        Posté par  . Évalué à 2.

        Que la classe de base soit un template ne change rien du tout, le compilo va etendre ton template avant de s'occuper de la classe derivee et tu te retrouveras exactement dans le meme cas que si la classe de base etait une classe basique.

        Template ou pas = 0 difference, le resultat final est identique.

        Les templates n'influent absolument pas sur le code genere a la fin, ils permettent simplement de ne pas reecrire 10x fois la meme chose.
        • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

          Posté par  . Évalué à 1.

          Donc a priori et à part les explicit, il n'y aurait aucune raison pour laquelle je ne pourrais pas faire çà :

          class BiduleContainer : public DataVector
          {}

          int main(int argc, char* argv[])
          {
          std::vector<Bidule*> desBidules;
          fillBidules(desBidules);

          BiduleContainer bidules(desBidules.begin(); desBidules.end());
          return 0;
          }

          J'ai bon ?
          Mais alors d'où vient mon erreur de compil' ? (C'est une question de pure réthorique, je vous demande pas non plus de programmer à ma place ;))
          • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

            Posté par  . Évalué à 3.

            A priori, si tu fais tout correctement oui.

            Maintenant, on va pas pouvoir t'expliquer ton erreur de compil si tu ne dis pas ce qu'est cette erreur de compilation, on n'a pas tous des talents de voyant...

            Si ce que tu viens de taper est ce que tu as dans ton code, le gros probleme evident que c'est que :

            class BiduleContainer : public DataVector

            ne specifie pas le type de DataVector(puisque c'est un template, faut preciser sur quel type il opere)

            Genre faudrait faire :

            class BiduleContainer : public DataVector< int >
            • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

              Posté par  . Évalué à 1.

              Ouaip, c'est vrai que tout le monde ne s'appelle pas John Smith.
              J'ai répondu un peu trop vite et un peu trop tôt dans la matinée.

              Donc, oui, c'est bien class BiduleContainer : public DataVector
              que j'ai dans mon code.

              Lorsque j'essaye d'instancier un container de Bidule-s via :
              BiduleContainer bidules( selectionDeBidules.begin(), selectionDeBidules.end() );

              J'ai çà comme erreur de compilation :
              bidulesSelect.cxx:541: no matching function for call to `
              BiduleContainer::BiduleContainer(
              __gnu_cxx::__normal_iterator<Bidule**, std::vector<Bidule*,
              std::allocator<Bidule*> > >,
              __gnu_cxx::__normal_iterator<Bidule**, std::vector<Bidule*,
              std::allocator<Bidule*> > >)'
              BiduleContainer.h:21: candidates
              are: BiduleContainer::BiduleContainer()
              bidulesSelect.cxx:239:
              BiduleContainer::BiduleContainer(const BiduleContainer&)

              Donc si je comprends bien ce que me dit gcc3.2, il ne voit que les constructeurs par défaut et par copie, automatiquement générés par le compilo. Et pas ceux de la classe de base (DataVector).

              En tout cas merci de tes réponses.
    • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

      Posté par  . Évalué à 2.

      heuuu, t'as essayé ton exemple avant de poster ?
      Je pense pas, il manques les points virgules à la fin de la déclaration des classes)

      Et ça ne marche pas, les constructeurs ne sont pas hérités (cf le message de Roulious). D'ailleurs gcc (3.2.3) me lance un warning :
      base `A' with only non-default constructor in class without a constructor

      D'ailleurs d'aprés mes souvenir de prog objet, le fait que les constructeurs ne soient pas hérités est logique. A et B sont deux types différents, on ne peut donc pas les instancier de la même façon. En y réfléchissant, les rares langages de POO que je connais ne le font pas.

      En c++, si je ne me trompe pas, les seuls constructeurs implicites sont le contructeur par defaut et le constructeur par copie. Il ne sont ajoutés que si l'utilisateur ne défini pas lui même des contructeurs.

      Un cpp-guru pour clarifier ?
      • [^] # Re: Ben oui, c'est le principe de la prog objet quand même ...

        Posté par  . Évalué à 1.


        En c++, si je ne me trompe pas, les seuls constructeurs implicites sont le contructeur par defaut et le constructeur par copie. Il ne sont ajoutés que si l'utilisateur ne défini pas lui même des contructeurs.

        C'est presque ça : un constructeur par défaut est ajouté uniquement s'il n'y a aucun autre constructeur défini, que ce soit un constructeur de copie ou un autre constructeur. Pour le constructeur de copie, il est effectivement ajouté lorsque l'utilisateur n'en définit pas un lui même.
  • # Les constructeurs ne sont pas des fonctions membre

    Posté par  . Évalué à 1.

    Vu que les constructeurs ne sont pas des fonctions membre (même s'ils en ont la syntaxe), ils ne sont pas hérités. Il va donc falloir les ré-implémenter explicitement.

    Je n'ai rien vu dans la Boost qui permettrait de faire ça, mais je n'ai pas trop cherché.

    Est-tu sur que tu as absolument besoin d'un héritage ?
    • [^] # Re: Les constructeurs ne sont pas des fonctions membre

      Posté par  . Évalué à 1.

      Ce que j'avais vu dans Boost c'etait ca :
      http://www.boost.org/libs/optional/doc/optional.html#inplace(...)

      Bon ensuite, au niveau de l'heritage...
      L'heritage n'est pas a priori necessaire (un typedef pourrait suffir) pour l'utilisation en elle-meme de la classe.
      Cependant, il me faut surcharger des fonctions necessaires lors de la relecture (des objets instanties) a partir de fichiers sur disque (RTTI toussa quoi, du genre identification du type d'objet stocke (son nom, son espace de serialisation,... ) ).

      Donc bon.
      Apparemment pas de solution miracle. C'est vraiment trop injuste :P
      Mais merci de ta reponse.

Suivre le flux des commentaires

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