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 :

containeur et héritage


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 95
    Points : 62
    Points
    62
    Par défaut containeur et héritage
    Bonjour à tous,
    Je vous pose un problème, sans doute très simple, mais j'ai un soucis et ça commence à me rendre fou. Je suis assez pressé dans mon travail, c'est pour cela que je me permets de vous demander votre avis.

    J'ai une classe AbstractColumn qui est virtuelle pure. Ensuite, deux classes HColumn et DColumn qui héritent de AbstractColumn.

    Plus loin, dans une autre classe Array, j'ai un objet qui contient différentes colonnes. J'ai implémenté cela avec un vector<AbstractColumn*> cols.
    N'existe-t-il pas une meilleure manière de stocker mes différentes colonnes ?

    Actuellement, je devrais faire cols.push_back(&HColumn(blabla)); pour ajouter des éléments dans le vector, mais ça ne fonctionnera pas.

    Je vous remercie par avance.

  2. #2
    r0d
    r0d est actuellement connecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    Citation Envoyé par Pg043 Voir le message
    N'existe-t-il pas une meilleure manière de stocker mes différentes colonnes ?
    Il existe plusieurs façon de procéder. La meilleure dépend de ton contexte.
    . Celle que tu as choisi est la plus "classique".
    . boost::variant est sans doute le plus simple, mais c'est apparemment plutôt lent
    . il existe des solutions à base de typelist (voir ici par exemple).

    Citation Envoyé par Pg043 Voir le message
    cols.push_back(&HColumn(blabla)); ne fonctionnera pas.
    En géneral, dans ton cas, on va plutôt faire un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cols.push_back(new HColumn(blabla));
    Ce qui signifie que c'est le vecteur col qui possède la nouvelle colonne.
    Mais là encore, la meilleure façon de procéder dépendra beaucoup de ton contexte.


    edit: Dans tous les cas, lorsque tu crée un objet destiné à être stocké dans un conteneur, il est important de faire spécialement attention aux constructeurs, et en particulier le constructeur par copie.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 95
    Points : 62
    Points
    62
    Par défaut
    Ah mais évidemment que je dois faire un new HColumn... Désolé !
    Concernant ton edit sur les constructeurs par copie, j'imagine que cela signifie que je dois implémenter le contructeur par copie de chacune de mes classes...
    Merci de ton aide

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 95
    Points : 62
    Points
    62
    Par défaut
    Ce premier problème étant corrigé, je me permets de vous solliciter pour un second.

    J'ai donc 4 classes que voici : TempArray, qui contient un vector<TempAbstractColumn*>; une classe virtuelle pure TempAbstractColumn et deux classes filles, TempColumnH et TempColumnD ! C'est 4 classes me permettent (entre autre) de définir la configuration de mon tableau.

    Maintenant, je voudrais implémenter la même hiérarchie pour, non plus la configuration du tableau, mais le tableau lui même. J'aurai donc 4 nouvelles classes : Array qui héritera de TempArray et contiendra un vector<AbstractColumn*>; une classe virtuelle pure AbstractColumn qui héritera de TempAbstractColumn et deux classes filles, ColumnH et ColumnD qui hériteront également respectivement TempColumnH et TempColumnD !

    Mon objectif est de pouvoir construire mon Array en fonction d'un TempArray. Problème : comment convertir le contenu du vector<TempAbstractColumn*> dans le vector<AbstractColumn*> ???

    Merci d'avance

  5. #5
    r0d
    r0d est actuellement connecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Pg043 Voir le message
    Concernant ton edit sur les constructeurs par copie, j'imagine que cela signifie que je dois implémenter le contructeur par copie de chacune de mes classes...
    En vérité ça dépend. Par exemple, si ces classes sont des POD et qu'elles n'ont pas de comportements farfelus, le copy-ctor par défaut peut suffire. Idem pour l'opérateur d'assignation. C'est pourquoi je dit qu' "il faut y faire attention": ce n'est pas forcément obligé, mais il faut faire gaffe.
    Car en fait, lorsqu'on stocke des objets dans un conteneur et qu'on y applique des traitements, il va forcément y avoir des copies, plus ou moins cachées.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  6. #6
    r0d
    r0d est actuellement connecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Pg043 Voir le message
    Problème : comment convertir le contenu du vector<TempAbstractColumn*> dans le vector<AbstractColumn*> ??
    Le détail de l'implémentation dépend de ton contexte, mais grosso-modo ça devrait ressembler à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void GenerateArray( const TempArray & src, Array & result )
    {
       for ( vector<TempAbstractColumn*>::const_iterator it = src.Begin(); it != src.End(); ++it )
          result.PushBack( new AbstractColumn( *it ) );
    // ce qui suppose que sont implémentés:
    // 1. des fonctions pour parcourir le tableau de TempAbstractCol contenu dans TempArray (ici j'ai fait comme s'il existait Begin() et End())
    // 2. une fonction pour ajouter des AbstractColumn à la classe Array (ici j'ai utilisé PushBack)
    // 3. un constructeur de AbstractColumn qui prend un TempAbstractColumn en paramètre
    }
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 95
    Points : 62
    Points
    62
    Par défaut
    Citation Envoyé par r0d Voir le message
    Le détail de l'implémentation dépend de ton contexte, mais grosso-modo ça devrait ressembler à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void GenerateArray( const TempArray & src, Array & result )
    {
       for ( vector<TempAbstractColumn*>::const_iterator it = src.Begin(); it != src.End(); ++it )
          result.PushBack( new AbstractColumn( *it ) );
    // ce qui suppose que sont implémentés:
    // 1. des fonctions pour parcourir le tableau de TempAbstractCol contenu dans TempArray (ici j'ai fait comme s'il existait Begin() et End())
    // 2. une fonction pour ajouter des AbstractColumn à la classe Array (ici j'ai utilisé PushBack)
    // 3. un constructeur de AbstractColumn qui prend un TempAbstractColumn en paramètre
    }
    1. j'utilise un vector, donc begin() et end() existe, je suis d'accord.
    2. idem pour le push_back, je suis d'accord.
    3. Mais ici, AbstractColumn est une classe virtuelle pure, donc, sans constructeur, ainsi, je n'ai pas de constructeur de AbstractColumn qui prend un TempAbstractColumn. Tout ce que je possède, c'est une classe ColumnH dont son constructeur prend un TempColumnH et une classe ColumnD dont un constructeur prend un TempColumnD !

    Pour le reste, je suis entièrement d'accord, mais c'est précisément sur ce troisième point que je n'arrive pas à résoudre le problème...

    Merci pour tout

  8. #8
    r0d
    r0d est actuellement connecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Mhh ok je vois le problème. Et à vrai dire, je ne vois pas trop comment faire...
    Il y aurait bien des solutions... mais c'est gore, j'ai un peu honte de proposer ça...
    Tu as l'air pressé, alors voici une proposition, mais c'est vraiment horrible:
    Ajouter un moyen de différencier une TempColumnH et une TempColumnD:
    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
    class TempAbstractColumn
    {
    protected:
       virtual const int Id() const = 0; // un identifiant, je le met en protected pour limiter la casse
    };
     
    class TempColumnH : public TempAbstractColumn
    {
       friend class ColumnFactory;
     
    private:
       const int Id() const { return 1; }
    };
     
    class TempColumnD : public TempAbstractColumn
    {
       friend class ColumnFactory;
     
    private:
       const int Id() const { return 2; }
    };
    Puis passer par une factory:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class ColumnFactory
    {
       public:
          static AbstractColumn * CreateColumn( const TempAbstractColumn * src )
          {
             if ( src->Id() == 1 )
                return new ColumnH( reinterpret_cast< const TempColumnH* >( src ) );
             else if ( src->Id() == 2 )
                return new ColumnD( reinterpret_cast< const TempColumnD* >( src ) );
             else
                // probleme
          }
    };
    Mais bon, le fait qu'on en arrive là montre qu'il y a des soucis dans ta conception. Notemment, pourquoi tant d'héritage?

    ps1: tout ce que je propose ici n'est pas testé, et ça ne doit certainement pas compiler en l'état.

    ps2: je réfute toute responsabilité dans l'utilisation d'une telle technique, et je nierai, même sous la torture, avoir jamais écris ce bout de code
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 95
    Points : 62
    Points
    62
    Par défaut
    Ok, merci de ton aide.
    J'avais commencé à regarder l'histoire de factory, puis j'ai pu lire ça et là que le reinterpret_cast n'est pas franchement terrible.
    Effectivement, je pense que je vais revoir un peu la conception avant d'aller plus loin.
    Merci tout de même

  10. #10
    Invité
    Invité(e)
    Par défaut
    Pourquoi utiliser un reinterpret_cast ? Un static_cast conviendrait mieux dans ce cas... (ou un dynamic_cast lors du deboggage pour ne pas avoir de surprises si les identifiants ont été mal affectés)

  11. #11
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Ou sinon tu demandes de construire un Array au TempArray, qui va à son tour demander aux TempAbstractColumn de construire leur AbstractColumn qui leur correspond.

    MAT.

Discussions similaires

  1. template et héritage de containeur
    Par Gébix dans le forum C++
    Réponses: 9
    Dernier message: 15/06/2012, 21h59
  2. [Postgresql]Héritage
    Par lheureuxaurelie dans le forum PostgreSQL
    Réponses: 13
    Dernier message: 02/10/2008, 10h18
  3. [Postgres] Héritage + Clés
    Par k-reen dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 21/05/2003, 17h37
  4. Containeur pour un assemblage d'images
    Par Amenofis dans le forum Composants VCL
    Réponses: 3
    Dernier message: 28/02/2003, 16h10
  5. Héritage entre Forms
    Par BarBal dans le forum Composants VCL
    Réponses: 7
    Dernier message: 29/08/2002, 18h44

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