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 :

Collection d'objets de types différents ?


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Avatar de sylvain1984
    Homme Profil pro
    Retraité, développeur amateur
    Inscrit en
    Juillet 2023
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Charente (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité, développeur amateur

    Informations forums :
    Inscription : Juillet 2023
    Messages : 72
    Par défaut Collection d'objets de types différents ?
    Bonjour,

    J'utilise QT 6.4 et en particulier sa classe QSettings qui offre une gestion d'un fichier de configuration assez simple.
    Mais je trouve un peu dommage, à chaque fois que je souhaite accéder à une variable, de devoir faire la chose suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    QSetting _preferences;
     
    // Pour lire une préférence
    _preferences.beginGroup("MonGroupeDePreferences");
         bool b = _preferences.value("UneCle").toBool(); // value() retourne un QVariant qu'il faut typer chaque préférence, du type :
    _preferences.endGroup();
     
    // Pour écrire une préférence :
    _preferences.beginGroup("MonGroupeDePreferences");
         _preferences.setValue("UneCle",bool value);
    _preferences.endGroup();
    C'est certainement beaucoup mieux que rien, mais à la longue ça agace un peu.

    J'ai donc pensé à encapsuler un QSetting par une classe contenant des get/set pour chaque préférence, plus quelques fonctions de maintenance. Mais je me retrouve avec une collection de fonctions dupliquant énormément de code. Par exemple, voici un get :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    bool MyPrefs::getModeDemo(){
        bool b = false;
        _preferences.beginGroup(grpApp);
        QStringList keys = _preferences.childKeys();
        if (keys.contains(modeDemoKey)){
            b = _preferences.value(modeDemoKey).toBool();
        }else{
            _preferences.setValue(modeDemoKey,modeDemoVal);
            b = modeDemoVal;
        }
        _preferences.endGroup();
        return b;
    }
    De base, pour accéder à une préférence, il faut le nom de sa clé et son type. J'ai alors pensé à créer une classe template pour stocker chaque préférence :
    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
    template<class T>
    class OnePref {
    public:
        OnePref()                   = delete;
        OnePref(OnePref &t)         = delete;
        OnePref operator=(OnePref)  = delete;
     
        OnePref(QSettings * prefs, QString grp, QString cle, T valDefaut)  {
            set_prefs_obj(prefs);
            _groupe = grp;
            _cle = cle;
            _valeur_defaut = valDefaut;
        }
        ~OnePref(){};
     
        T get_valeur() {
            QVariant v = get_value_as_QVar();
            if (v.canConvert<T>(v)) return v.value<T>();
            else v.clear();
        }
    };
    L'idée est ensuite de stocker toutes les préférences comme des pointeur vers ces objets patron dans une Map dont la clé est celle de la préférence. Je sais, ça duplique la clé de la préférence, mais je crois que c'est rapide...
    Mais le compilateur n'est logiquement pas ok : les pointeurs ne pointent pas vers un même type.

    D'où l'idée ensuite de créer une classe virtuelle de laquelle hérite les objets préférence, puis de placer un pointeur vers cette classe virtuelle dans la Map.

    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
    class AbstractPref {
    public:
        AbstractPref():__preferences(nullptr){};
        virtual ~AbstractPref(){};
        void set_prefs_obj(QSettings * p) { if (p) __preferences = p; }
     
        QString     get_groupe()        const { return _groupe;       }
        QString     get_cle()           const { return _cle;          }
        QSettings * get_pref_obj()      const { return __preferences; }
        QVariant    get_value_as_QVar()             const;
        void        set_value_as_QVar(QVariant &v)  const;
     
        QSettings * __preferences;
        QString     _groupe;
        QString     _cle;
        QVariant    _valeur_defaut;
    };
     
    class OnePref  : public AbstractPref { /*..*/ };
     
    class MyNewPrefs {
    public:   MyNewPrefs();
        ~MyNewPrefs();
     
        void ajouter_preferences(AbstractPref * p) { _all_prefs[p->get_cle()] = p; }
     
    private:
        void set_prefs();
        QSettings                   _preferences;
        QMap<QString,AbstractPref*> _all_prefs;
    };
    Ça fonctionne. Sauf que pour accéder à une préférence il va me falloir transtyper _all_prefs["UneCle"] (ligne 30) qui renvoi un AbstractPref*, ce qui n'est pas dans l'esprit de ce que je souhaite faire.

    Typiquement, j'aimerais pouvoir faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool b = _all_prefs["UneCleBool"].value();
    J'ai relu mon Stroustrup sur l'héritage et les classes patrons, sans avancer vraiment.

    J'envisage d'ajouter dans la classe virtuelle une variable par type utilisé et un indice vers le type à utiliser...

    Est-ce que c'est possible ce genre de chose ?

    Sylvain

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 527
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 527
    Par défaut
    J'ai du mal à comprendre votre démarche de "customisation" de la classe "MyPrefs".

    Si c'est pour factoriser du code, pourquoi ne pas le faire sous forme de fonctions privées ?

    Je pense qu'une classe type "MyPrefs" n'est pas qu'un accesseur à fichier de conf. :
    - mécanisme de compatibilité ascendante
    - mécanisme de "failback"
    - etc...

    Donc templetiser complètement le traitement interne de ce type de classe ne me parait pas un "move naturel".

    J'ai l'impression que vous voulez transformer votre "MyPrefs" en une simple QMap++.

  3. #3
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 763
    Par défaut
    Citation Envoyé par sylvain1984 Voir le message
    Typiquement, j'aimerais pouvoir faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool b = _all_prefs["UneCleBool"].value();
    Je pense que le problème de base est là: vouloir un type différent en sortie sans avoir un type différent en entrée.

    Plutôt que de manipuler une clef sous forme de string, il faudrait plutôt une clef qui regroupe type et nom. Quelque chose comme cela:

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    template<class T>
    struct PropertyTraits { static_assert(!sizeof(T), "missing specialization on T"); };
     
    // implémentation pour le type bool
    template<>
    struct PropertyTraits<bool>
    {
       static bool get(QVariant var)
      {
        return var.toBool(p);
      }
     
      static void set(QSettings & settings, QStringView key, bool value)
      {
        settings.setValue(key, value);
      }
    };
     
    // code commun pour tous les types
    template<class T, class Traits = PropertyTraits<T>>
    struct Property
    {
      QStringView key;
      T (*defaultValueMaker)() = []{ return T{}; };
     
      T read(QSettings const & settings) const
      {
        return Traits::get(settings.value(key));
      }
     
      template<class ValueMaker>
      T readOr(QSettings const & settings ValueMaker && valueMaker) const
      {
        // À voir si pour toi utiliser QVariant::canConvert() est mieux.
        if (settings.contains(key)) {
          return Traits::get(settings.value(key));
        }
        return std::forward<ValueMaker>(valueMaker)();
      }
     
      T readOrDefault(QSettings const & settings) const
      {
        return readOr(settings, defaultValueMaker);
      }
     
      // si tous les types map ceux de settings, on peut se contenter de settings.setValue(key, value);
      // mais le trait à l'avantage de gérer les types qui seraient incompatibles avec QVariant, par exemple: std::chrono::seconds.
      void write(QSettings const & settings, T && value) const
      {
        return Traits::set(settings, key, std::move(value));
      }
     
      // On pourrait n'avoir qu'une version de write() qui prend un `T`, mais cela fait une copie qui peut être évité dans le cas de QString.
      // On pourrait aussi prendre un `U&&` et forward() vers Traits::set() qui a l'avantage de déplacer la transformation du type dans le trait.
      void write(QSettings const & settings, T const& value) const
      {
        return Traits::set(settings, key, value);
      }
    };
     
    template<auto v>
    inline constexpr defaultValue = []{ return v; };
    Et qui s'utiliserait ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    inline constexpr Property<bool> uneClefDeBool { u"groupe/clef" };
    // ou en spécifiant une valeur par défaut
    inline constexpr Property<bool> uneClefDeBool { u"groupe/clef", defaultValue<true> };
    // ou (forme obligée pour QString / QStringLiteral qui ne sont pas des types constexpr ou structurel)
    inline constexpr Property<bool> uneClefDeBool { u"groupe/clef", []{ return true; } };
     
    bool b = uneClefDeBool.read(settings);
    uneClefDeBool.write(settings, false);
    je n'ai pas testé, mais il y a les grandes lignes. Après tu peux faire un wrapper sur QSettings si la forme clef.function(settings) dérange et que tu préfères avoir settings.function(clef).

  4. #4
    Membre éclairé
    Avatar de sylvain1984
    Homme Profil pro
    Retraité, développeur amateur
    Inscrit en
    Juillet 2023
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Charente (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité, développeur amateur

    Informations forums :
    Inscription : Juillet 2023
    Messages : 72
    Par défaut
    Bonjour,

    Merci beaucoup pour vos réponses.

    Après avoir lu votre solution @bacelar, (avant un gros dodo...) j'ai effectivement testé avec bonheur la fonction template privée :
    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
    template<class T> T get_pref(QString const & key){
            T val;
            _preferences.beginGroup(whichGrp[key]);
            if (_preferences.childKeys().contains(key)){
                val = _preferences.value(key).value<T>();
            }else{
                _preferences.setValue(key, whichdefault[key]);
                val = whichdefault[key].value<T>();
            }
            _preferences.endGroup();
            return val;
        }
        template<class T> void set_pref(QString const & key, T const & val){
            _preferences.beginGroup(whichGrp[key]);
                val = _preferences.setValue(key,val);
            _preferences.endGroup();
        }
    Cela simplifie en effet énormément le code que je vais pouvoir basculer dans l'entête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    bool MyPrefs::getNomMin(){
        return get_pref<bool>(nomMinKey);
    }
    whichGrp[key] et whichDefaultGrp[key] sont deux QMap liants la clé à, respectivement, son groupe et à sa valeur par défaut (un QVariant).
    Ça à l'air de fonctionner, je n'ai pas encore migré en totalité.

    Quant à la solution de @jo_link_noir, je vais la digérer tranquillement.

    Merci encore,
    Sylvain

  5. #5
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    701
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 701
    Par défaut
    Salut à tous,

    Petite parenthèse d'abord, préfixer les noms de variable de tiret(s) bas, sauf cas particulier, fait définitivement partie des mauvaises pratiques.

    Cela dit, @sylvain1984, tu ne présentes qu'une vue assez sommaire de ta problématique. En l'état, et après une lecture en diagonale de QSettings (je ne connais pas Qt, ou que de nom), j'écrirais qu'un simple auto x= prefs.value<bool>("group/key"); devrait suffire.

    En fait, pour ton code, le type de transtypage doit être connu ou déduit à la compilation. C'est pour cette raison que tes QSettings sur base de variants ou unions like te font tourner en rond. Assurément, tu as un problème de design quelque part, et le peu que j'en vois préfigure déjà des bugs latents.

  6. #6
    Membre éclairé
    Avatar de sylvain1984
    Homme Profil pro
    Retraité, développeur amateur
    Inscrit en
    Juillet 2023
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Charente (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité, développeur amateur

    Informations forums :
    Inscription : Juillet 2023
    Messages : 72
    Par défaut
    Bonjour @kaitlyn,

    Merci pour ton retour !

    Citation Envoyé par kaitlyn Voir le message
    Petite parenthèse d'abord, préfixer les noms de variable de tiret(s) bas, sauf cas particulier, fait définitivement partie des mauvaises pratiques.
    Petite précision préalable : comme l'indique le texte sous mon avatar je suis un développeur du dimanche, à la retraite désormais, assez mordu mais pas pro car pas formé ad-hoc. Dans mon boulot j'ai développé et fait développer de petites appli intégrant des algos de RO. Mes connaissances m'ont tout de même permis de demander à une société d'informatique de changer le type d'un conteneur, ce qui a réduit les délais une fonction d'un facteur de 5.
    Comme j'ai plus de temps j'aime à apprendre au travers d'une appli pour une association. Je suis dessus depuis deux ans...
    Aussi je suis très heureux quand j'ai un retour comme les vôtres. Merci encore !


    Concernant le tiret bas devant les variables, j'ai pris cette habitude récemment pour distinguer les variables de la classe des variables locales aux fonctions de cette même classe. En quoi c'est une mauvaise pratique ?

    Citation Envoyé par kaitlyn Voir le message
    Cela dit, @sylvain1984, tu ne présentes qu'une vue assez sommaire de ta problématique. En l'état, et après une lecture en diagonale de QSettings (je ne connais pas Qt, ou que de nom), j'écrirais qu'un simple auto x= prefs.value<bool>("group/key"); devrait suffire.
    Oui, c'est la solution que j'ai finalement retenu. Je voulais mettre en œuvre un patron pour réduire le code. J'étais parti sur un truc trop compliqué, voire impossible. Mais j'ai trouvé plus simple avec la méthode postée le 11 dernier ci-dessus grâce à l'indication de @bacelar.

    Citation Envoyé par kaitlyn Voir le message
    En fait, pour ton code, le type de transtypage doit être connu ou déduit à la compilation. C'est pour cette raison que tes QSettings sur base de variants ou unions like te font tourner en rond. Assurément, tu as un problème de design quelque part, et le peu que j'en vois préfigure déjà des bugs latents.
    design... design... je ne te rassurerai pas en te disant qu'il n'y en a jamais eu pour mon soft... Comme on dit vulgairement dans mon boulot, je suis parti "vent du c*l dans la plaine", persuadé de plier ça en une semaine... Comme le dirait M Robert C. Martin, mon code doit sentir horriblement mauvais...
    Je manque en fait d'un langage de description comme UML. J'ai installé Modelio sur ma Debian et je caresse l'espoir d'y consacrer enfin le temps nécessaire quand le périmètre fonctionnel de l'appli sera couvert, ce qui ne saurait tarder !

    Bonne soirée !
    Sylvain

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 527
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 527
    Par défaut
    Concernant le tiret bas devant les variables, j'ai pris cette habitude récemment pour distinguer les variables de la classe des variables locales aux fonctions de cette même classe. En quoi c'est une mauvaise pratique ?
    https://softwareengineering.stackexc...e-the-compiler
    Donc, vous risquez des emmerdes de oufs avec des compilateurs, au pire moment, comme d'hab.

    Plutôt que de prendre des conventions qui viennent d'autres langages qui ne matchent pas avec le C++, vous pouvez vous tourner vers une utilisation raisonnée de la notation hongroise :
    "m_..." pour des membres d'une classe
    "s_..." pour les statiques d'une classe
    "p_..." pour des paramètres (si nécessaire et surement pas pour des pointeurs)
    "l_..." pour une variable locale (même si je trouve cela un peu lourd et inutile).
    "g_..." beurk...

  8. #8
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 763
    Par défaut
    L'histoire de ne pas préfixer par un underscore est une simplification de la règle des identifiants réservés. Dans une classe, ce n'est pas un problème. À condition de ne pas suivre par une majuscule.

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 524
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 524
    Par défaut
    Citation Envoyé par bacelar Voir le message
    https://softwareengineering.stackexc...e-the-compiler
    Donc, vous risquez des emmerdes de oufs avec des compilateurs, au pire moment, comme d'hab.

    Plutôt que de prendre des conventions qui viennent d'autres langages qui ne matchent pas avec le C++, vous pouvez vous tourner vers une utilisation raisonnée de la notation hongroise :
    "m_..." pour des membres d'une classe
    "s_..." pour les statiques d'une classe
    "p_..." pour des paramètres (si nécessaire et surement pas pour des pointeurs)
    "l_..." pour une variable locale (même si je trouve cela un peu lourd et inutile).
    "g_..." beurk...
    A la limite, le préfixe "m" pour les membres de la classe histoire d'éviter de désambiguïser via le pointeur this (c'est lourdingue), tous le reste est inutile.
    Un nom clair, explicite et précis vaut toutes les conventions du monde.

  10. #10
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    701
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 701
    Par défaut
    Salut,

    Citation Envoyé par jo_link_noir Voir le message
    L'histoire de ne pas préfixer par un underscore est une simplification de la règle des identifiants réservés. Dans une classe, ce n'est pas un problème. À condition de ne pas suivre par une majuscule.
    Le standard se réserve aussi le tiret bas + minuscule (ou chiffre). Dans ce cas, il subsiste quand même un risque de collision, ou pire, de liaison avec des identifiants globaux. C'est vite arrivé, une simple erreur de masquage au niveau de la classe suffit. Toutefois, dans la pratique, le problème viendra plus du côté des bibliothèques prépondérantes que des implémentations du standard lui-même (ah, peut-être que pour la C Runtime si).

    Citation Envoyé par sylvain1984 Voir le message
    design... design... je ne te rassurerai pas en te disant qu'il n'y en a jamais eu pour mon soft...
    Le design n'a rien à voir avec oncle Bob ou UML et ne préjuge d'aucune préparation ou formalisation en amont. C'est soit un constat d'a posteriori, soit une vue sur le cheminement dont il est le fruit, c'est-à-dire la raison ou l'ensemble des choix et décisions qui ont mené à cette réalisation. Donc oui, il y a bien du design dans ton soft, et potentiellement le souci évoqué plus tôt.

  11. #11
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 763
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Le standard se réserve aussi le tiret bas + minuscule (ou chiffre).
    Non, les règles du standard comme indiqué dans mon lien vers cppreference sont:

    - double underscore n'importe où
    - commence par underscore + majuscule
    - commence par underscore dans le namespace globale seulement

    À cela s'ajoute E suivit de nombre ou lettre majuscule qui sont définis par les implémentations liées à errno.

    Dire que l’underscore est un préfixe réservé est donc une simplification. Mais si tu veux, regarde la section 5.11.3 du standard: https://timsong-cpp.github.io/cppwp/lex.name#3 (Lexical conventions, Identifiers).

    Pour le risque de collision, je te rassure, ils existent même sans préfixe. Quand on voit que les en-têtes systèmes font de la sélectionner de nom de fonction à base de macro, c'est pas terrible. Un petit stat qui se transforme magiquement en stat64 en fonction des includes :/

  12. #12
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    701
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 701
    Par défaut
    Salut tout le monde,

    Dans mon message précédent @jo_link_noir, qui est plutôt complémentaire à la citation en référence et aux liens, il est bien question de l'espace de nom global. Donc je ne comprends pas trop ce à quoi tu réponds. Il te suffisait de ne pas t'arrêter à la première ponctuation.
    Je me répète, mais j'y exposais simplement le risque de liaison silencieuse avec des identifiants ou symboles, éventuellement à usage interne, et pas forcement documentés. La collision étant bien sûr ce qu'il peut arriver de mieux.

    Pour ton dernier paragraphe qui parle d'API, tu en conviendras, c'est carrément hors sujet

    Après, il n'est pas question pour moi d'épiloguer plus que ça sur cette parenthèse (de préfixe) que j'ai toutefois ouverte.

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 31/08/2015, 08h19
  2. Comment faire de la defensive copie avec un objet de type Collection
    Par l_informaticien dans le forum Collection et Stream
    Réponses: 12
    Dernier message: 20/01/2013, 21h56
  3. Réponses: 7
    Dernier message: 26/04/2011, 18h00
  4. Réponses: 4
    Dernier message: 23/02/2010, 16h33
  5. [VB6] Sauvegarder une collection d'objets
    Par Sayagh dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 19/09/2003, 11h58

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