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 :

[Langage] Initialisation d'un vecteur membre statique


Sujet :

Langage C++

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut [Langage] Initialisation d'un vecteur membre statique
    Bonjour,

    Soit une hiérarchie de classes. Seules certaines d'entre elles seront directement instanciées (bien qu'elles soient pour l'instant toutes instanciables...).

    Je voudrais que chacune des classes instanciables continne un vecteur de chaînes de caractères, dont le contenu est spécifique à cette classe, et commun à toutes ses instances. Ce qui nous amène donc à la déclarer statique.

    Pour m'assurer de la présence de ce vecteur, je souhaitais donc le déclarer dans la classe parente, bien que seules certaines de ces classes dérivées vont remplir ce vecteur. Y a-t-il une méthode plus intelligente ?

    Si je reste sur cette conception, comment puis-je initialiser le vecteur de manière statique ?

    Merci.

  2. #2
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Bonjour,

    Attention, si tu déclares le vecteur dans la classe parent, toutes les classes dérivées vont partager le même vecteur.

    Pour initialiser un vecteur déclaré en static, tu peux appeler une fonction renvoyant un vecteur initialisé comme tu le souhaites :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    std::vector<int> vector_initializer()
    {
        std::vector<int> v;
        v.push_back(1);
        v.push_back(2);
        //…
        return v;
    }
     
    std::vector<int> my_class::my_vector = vector_initializer();
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Merci pour l'astuce d'initialisation !

    Mais y a-t-il un moyen de contraindre les classes instanciables à avoir un vecteur statique ?

    Quelque chose comme les fonctions virtuelles pures, mais pour une donnée...

  4. #4
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Tout ce que tu peux faire, c'est forcer les classes dérivées à implémenter un accesseur (ou un getter) pour ce vecteur.
    Étant donné qu'une donnée membre, même statique, doit de préférence (si ce n'est toujours) être privée (même pas protected), cela devrait suffire, non ?
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    OK, je vais faire comme ça.

    Merci.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Ce qui est dommage, c'est que le contenu de la fonction en question est identique quelle que soit la classe, mais que je ne peux la factoriser, parce qu'elle fait appel à une donnée statique qui n'est définie que plus bas dans la hiérarchie... :-/

  7. #7
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Eh oui, on ne peut pas toujours tout factoriser !

    Cela dit, tu peux utiliser le préprocesseur. C'est ce que je fais dans ces cas là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #define SOCOA_CPP_DEFINE_VISITABLE()    \
        void                                \
        accept(visitor& a_visitor) const    \
        {                                   \
            a_visitor.visit(*this);         \
        }
    Pense à bien préfixer le nom de ta macro avec quelque chose d'unique, comme par exemple le namespace de tes classes (dans le cas du dessus, le namespace est socoa::cpp). Il faut toujours utiliser le préprocesseur avec beaucoup de précautions.
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Je trouve que tout cela complexifie pas mal code. Ça me chagrine un peu.

    Je vais peut-être abandonner le statique, quitte à dupliquer des données. Après tout, ce n'est jamais qu'un vecteur d'une demi-douzaine de chaînes de moins de 10 caractères. Et comme c'est utilisé dans un algo déjà bien alambiqué...

    Bref, je me tâte....

  9. #9
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Je pense qu'il est toujours possible d'allier lisibilité et performances. Si tu choisis des noms de classes/fonctions/macros explicites avec une bonne convention de nommage, ça tient la route.

    Et dans ton cas, le code est compliqué mais les retombées sur les performances sont nulles vu que tout est préprocessé et inliné.
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Je vais faire autrement.

    J'ai la chance de disposer d'une association [type <-> chaîne de caractères].

    Je vais donc mettre dans ma classe parente une structure de données statique, constituée d'un
    map< string, vector<string> >
    Je définirai dans ma classe parente une méthode qui prend en paramètre le nom du type, et chaque classe dérivée appellera cette fonction avec comme paramètres le nom du type et la chaîne à rechercher dans le vecteur.

    Simple et efficace. :-)

  11. #11
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    Selon moi, le plus cohérent serait - outre la possibilité d'avoir la classe de base sous forme de template qui pourra être abordée plus tard - de déclarer une méthode virtuelle pure "init()" (par exemple) dans la classe de base (en n'oubliant pas que, du coup, la classe de base devient abstraite) et de déclarer le vecteur statique dans... les classes dérivées.

    Pour chacune des classes dérivées, "YAPUKA" réécrire, finalement, le même code, en l'adaptant aux valeurs à insérer en fonction de la classe imbriquée sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void Derivee::init()
    {
        if(tab.empty())
        {
            tab.push_back("chaine1");
            tab.push_back("chaine2");
            tab.push_back("chaine3");
            tab.push_back("chaine4");
            /* ... */
        }
    }
    L'idée reste identique pour la récupération et la recherche des valeurs contenues dans le vecteur
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par koala01 Voir le message
    outre la possibilité d'avoir la classe de base sous forme de template qui pourra être abordée plus tard -
    Tu penses à un truc genre CRTP ? genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Base {};
    template<class T>class Intermediate : public Base {static vector<string> v;};
    class Derivee1 : public Intermediate<Derivee1> {}
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Tu penses à un truc genre CRTP ? genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Base {};
    template<class T>class Intermediate : public Base {static vector<string> v;};
    class Derivee1 : public Intermediate<Derivee1> {}
    Exactement, ou, du moins, basé dessus...

    On pourrait séparer les responsabilités, et donc avoir d'un coté, une interface template responsable de la gestion du vecteur (avec les comportements adaptés), de l'autre une classe de base regroupant les autres comportements cohérents, et, au final, les classes instanciables héritant de l'interface (CRTP) et de la classe de base
    En spécialisant le constructeur de l'interface pour chaque type dérivé, il devrait être possible que tout se fasse tout à fait naturellement, et de manière transparente pour l'utilisateur de la classe instanciable
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Selon moi, le plus cohérent serait - outre la possibilité d'avoir la classe de base sous forme de template qui pourra être abordée plus tard - de déclarer une méthode virtuelle pure "init()" (par exemple) dans la classe de base (en n'oubliant pas que, du coup, la classe de base devient abstraite) et de déclarer le vecteur statique dans... les classes dérivées.
    Mais où est déclaré ton tab ?
    Si c'est dans le parent, toutes les classes dérivées profiteront de l'ajout des membres au vecteur.
    Si c'est dans la classe dérivée, je devrais copier en "local" le vecteur statique de la classe parent.

  15. #15
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Ah, je n'avais pas compris qu'il y avait une base commune au contenu du tableau de chaque élément...

    Dés lors, ce que l'on peut envisager, c'est d'avoir un tableau statique dans la classe mere et un tableau statique dans la classe fille (d'un autre nom), et de comparer la taille du tableau de la classe fille avec le nombre d'éléments contenu par le tableau de la classe mère dans la méthode nommée init...

    Si le nombre d'éléments du tableau de la classe fille est 0, on copie les éléments du tableau de la classe mère, puis on ajoute ceux qui sont propres à la classe fille.

    Si le nombre d'éléments du tableau de la classe fille est strictement identique à celui du tableau de la classe mère (ce qui ne devrait normalement jamais arriver), on ajoute dans le tableau de la classe fille les éléments qui lui sont propres

    Si, enfin, le nombre d'éléments du tableau de la classe fille est supérieur à celui du tableau de la classe mère, c'est que le tableau a déjà été correctement initialisé, et qu'il n'y a plus rien à faire
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 6
    Dernier message: 24/10/2011, 15h30
  2. Réponses: 5
    Dernier message: 21/07/2007, 12h30
  3. Réponses: 2
    Dernier message: 20/07/2007, 10h44
  4. Initialisation membre statique
    Par vandamme dans le forum C++
    Réponses: 6
    Dernier message: 06/07/2007, 20h59
  5. Réponses: 6
    Dernier message: 22/09/2006, 13h31

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