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++Builder Discussion :

STL list<> et VCL TList<>


Sujet :

C++Builder

  1. #1
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut STL list<> et VCL TList<>
    RAD Studio C++ 2007
    Je débute avec les templates !
    Je sais qu'à partir de 2009, avec l'ajout des génériques en Delphi, il est possible d'utiliser une TList<T> (generics.collection) qui reprend les méthodes de la TList habitudelle (classes)

    J'ai cru comprendre qu'utiliser les génériques Delphi par des Header de Template C++, cela semblait pas être très très joli !

    Que pensez vous de la STL list<> (Dinkumware) ?
    Quelle la différence entre std::list et std::vector, juste la possibilité d'utiliser [] ?

    en fait, j'ai pas envie d'écrire ce genre d'horreur : TfrmMain::ShowContacts() et la vilaine répétition de reinterpret_cast
    une petite surcharge de "void* Items[]" en "struct* Items[]" et cela inclue le cast dans l'accesseur !

    j'ai cru comprendre que la list provoquait la libération des éléments (voir la doc de la méthode erase : "Erasing N elements causes N destructor calls"), cela ne fonctionne que sur les classes ? est-ce cela supporte les struct ? les TObject ?
    Je ne veux pas libérer mes items, je veux juste stocker des struct*, et lorsque je vide la liste, je veux juste qu'il les oublie (ces struct* viennent d'ailleurs dans le code, tout est déjà nickel à ce sujet)

    EDIT : D'après mes Tests, cela n'appel le destructeur si <class*>, cela appel le constructeur de copie et le destructeur sur <class>

    Rien que trouver qu'il fallait écrire "std::list" et pas juste list tout court, j'ai bien du chercher une bonne minute !

    Enfin, migration sur XE prévue, j'aimerais prévoir le coup et remplacer rapidement std::vector par TList<> (logique autant utilisé la VCL, sinon inutile d'être sous RAD Studio)
    Pour le moment, je pars sur une TList + Accesseurs, par ceque la std::list ne me convient pas mais j'aimerais connaitre le ressenti à ce sujet des experts C++ Builder !

    Idem avec DynamicArray<> par rapport à la TList ou TList<> ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  2. #2
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2003
    Messages : 288
    Points : 334
    Points
    334
    Par défaut
    Je ne connais pas bien std::list puisque j'utilise TList en général, mais ça m'étonnerait que erase appelle les destructeurs. TList ne le fait pas non plus. A vérifier bien sur.

    La grande différence entre list et vector est que list est une liste chainée tandis que vector est un tableau (array). Chaque fois que tu ajoute un nouvel element dans vector le tableau est reconstruit (d'ou l'interêt de la methode reserve pour pré-allouer de la mémoire).
    De plus l'ajout/supression des elements d'un vector est optimisé quand on ajouter en fin de tableau, tandis que list permet les insertions.

    Donc utilise vector pour des listes finies et stables et list pour des listes plus dynamiques.

    > logique autant utilisé la VCL, sinon inutile d'être sous RAD Studio

    ça se discute. Pas mal de gens préfèrent utiliser les classes de la STL pour des questions de portabilité et d'homogénéité du code. Perso je considère que la VCL a un grand interêt pour concevoir les fenêtres mais pour le reste c'est moins évident.

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Merci de ta réponse Yarp

    Pour la destruction par erase de la std::list, j'ai testé :
    <class*> = pas de libération, heureusement
    <class> = constructeur de copie et le destructeur de la copie, ne touche pas à l'original, donc parfait !

    voir la doc de la méthode erase : "Erasing N elements causes N destructor calls", est peut-être un peu flou !

    vector est donc plus proche de TList, reserve étant l'équivalent de Capacity

    Pour une liste finie, autant prendre directement un tableau
    J'ai utilise la TList, mon prédecesseur a utilise massivement la TList et des struct*


    Se préoccuper de la portabilité d'un code avec RAD Studio, cela me fait bien rigoler !
    Faudrait donc cloisonner son code,
    une partie avec les strict standards C++ sans jamais aucune directive de RAD Studio,
    une autre partie pour les IHM à base de TForm ...

    Cela fait juste un code peu harmonieux, en fait pas du tout homogène, c'est de la perte d'énergie et de temps à mon avis !
    Je suis développeur Delphi, en fait la VCL est la seul lib par défaut dans Delphi et je suis curieux de ton avis sur
    mais pour le reste c'est moins évident.
    c'est quoi le reste ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2003
    Messages : 288
    Points : 334
    Points
    334
    Par défaut
    > Pour une liste finie, autant prendre directement un tableau

    Pas tout à fait. La différence entre un vector et un tableau est que vector est un tableau dynamique.
    Si par exemple tu lis un fichier pour charger ton vector. Avec un tableau tu dois lire le fichier d'abord pour compter les éléments, puis relire une 2ème fois pour initialiser le tableau. Tandis qu'avec un vector tu fais tout en une seule opération.

    > Se préoccuper de la portabilité d'un code avec RAD Studio, cela me fait bien rigoler

    C'est vrai. Mais ce que je voulais dire c'est que ça permet plus facilement de partager des classes entre plusieurs projets. J'ai des projects CBuilder et Visual Studio, et les classes que j'utilise pour les 2 ont std::vector pour les collections et CString au lieu de AnsiString.

    > Faudrait donc cloisonner son code
    > c'est de la perte d'énergie et de temps à mon avis

    je trouve que plus il y en a a l'exterieur de ces monstreux CPP/DFM et mieux c'est.
    Si tu as une fiche avec un TTreeView et un TDrawGrid le logique interne de chaque composant ne regarde en général pas l'autre.Mais c'est vrai que ça demande du travail. Je ne le fais que pour les composants importants.

    > c'est quoi le reste ?

    Il y a des tas de composants non graphiques qui peuvent être remplacés par des librairies C++ ou du code maison.
    En vrac: composants SMTP, common dialogs, TTimer, Themes, XML, TImage, TImageList, TBitBtn, le Custom Draw, TThread,...

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par yarp Voir le message
    Si par exemple tu lis un fichier pour charger ton vector.
    On n'a pas la même définition de liste finie ! Dans ton exemple, la liste n'est pas finie, c'est une liste dynamique !
    C'est pas grave, j'ai très bien compris ta remarque, et j'ai bcp bossé en Delphi sur l'anticipation d'allocation mémoire pour éviter les réallocations mais depuis FastMem inclu en 2007 qui a réduit le temps réallocations par 1000, cela n'a plus grand intérêt !

    Citation Envoyé par yarp Voir le message
    J'ai des projects CBuilder et Visual Studio !
    Ah oui tu es courageux !
    Personnellement, je préfère alors faire une DLL ou Objet COM, bcp moins de risque de faire des erreurs dans les sources partagées !
    Mais je n'ai jamais mélangés deux environs de développement "compatible", en général, j'avais Delphi+Java ou Delphi+PHP donc utilisation des technologique appropriés comme les WebServices !

    je trouve que plus il y en a a l'exterieur de ces monstreux CPP/DFM et mieux c'est.
    On est d'accord, je dois maintenir un projet dont 95% est du code est dans le CPP/DFM, c'est horrible, ils n(ont jamais entendu parlé de la séparation des couches de Présentation et Métier (peut-être pas aussi extrème qu'un MVC mais quoi que !)
    Même quand je codais tout en procédural, je faisais des unités séparées pour les types, les procédures de traitement et les TForm, je faisais une archi objet sans le savoir, je m'en suis rendu compte que bien plus tard !

    Citation Envoyé par yarp Voir le message
    Il y a des tas de composants non graphiques qui peuvent être remplacés par des librairies C++ ou du code maison.
    En vrac: composants SMTP, common dialogs, TTimer, Themes, XML, TImage, TImageList, TBitBtn, le Custom Draw, TThread,...
    Euh dans ta liste, il y a bcp de composants Graphiques ...

    Pour moi RAD Studio c'est aussi pour son énorme VCL, je ne vois vraiment aucun intérêt de l'acheter pour ne pas utiliser sa librairie intégrée !

    En même temps, je ne vois aucun intérêt à utiliser C++Builder * !
    Autant utiliser Delphi directement, le langage est plus simple, la VCL a été écrite pour et avec Delphi, le seul soucis, c'est le manque de header ... qui avec les versions très récente de RAD Studio ne sera (n'est ?) plus un problème, on pourra inclure un .h C++ dans un projet Delphi et peut-être même un fichier .lib (il n'y a un équivalent en Delphi, il faut le header)

    Je me suis amusé a intégrer une unité Delphi dans un Projet C++ 2007, c'est rigolo, cela génère le .h automatiquement !

    *Lorsque j'ai fait cette remarque, pourquoi choisir C++Builder plutôt que Delphi, la réponse fut : "le modèle objet de Delphi est trop limitatif"
    lol !
    1- Ils n'utilisent pas d'objet !
    2- Ils n'utilise pas la STL mais la VCL donc se limite au modèle objet de Delphi
    3- En fait, Visual C++ était trop pénible pour les IHM, c'est la seule vraie raison valable !

    J'ai failli bossé dans une boite où il codait les fenêtres en Visual Basic qui utilisait des DLL codées en Visual C++ !
    Tout ça pour éviter WinForm je suppose !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2003
    Messages : 288
    Points : 334
    Points
    334
    Par défaut
    > Personnellement, je préfère alors faire une DLL ou Objet COM, bcp moins de
    > risque de faire des erreurs dans les sources partagées !

    C'est un peu ce que je fais. J'ai des dialogues écrites en ATL/WTL dans des DLL que j'appelle depuis l'exe CBuilder. C'est comme ça que je gére les common dialogs par exemple.

    > Euh dans ta liste, il y a bcp de composants Graphiques

    Oui, aussi

    > En même temps, je ne vois aucun intérêt à utiliser C++Builder

    L'interêt c'est que le compilateur supporte le Pascal, le C++ et les librairies Microsoft (MFC & ATL) ce qui permet d'utiliser un grand nombre de librairies tierces qui sont pour la plupart natives C ou C++.
    Composants Pascal, STL, ATL, WTL, libjpeg (je travail dans l'image),... c'est vraiment très souple.

    > Je me suis amusé a intégrer une unité Delphi dans un Projet C++ 2007,
    > c'est rigolo, cela génère le .h automatiquement

    Oui, c'est ça qui est génial. On a un compilateur qui traite le Pascal et le C++ en même temps, c'est vraiment super.

    Et puis je suis plus à l'aise avec le C++ qu'avec le Pascal.

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    au final, j'utilise assez peu le list<> mais beaucoup la TObjectList que j'ai encapsulé par des templates !

    au début j'ai utilisé vector<int> que j'ai remplacé par set<int>
    j'ai aussi utilisé map<String, String>, c'est vraiment un truc qui manque en Delphi, j'avais codé la mienne !

    J'ai un doute sur lequel utilsé malgré les conseils de la FAQ Quel conteneur choisir pour stocker mes objets ?
    ai-je bien fait de passer de vector<int> à set<int>
    mes int sont des identifiants issus de la DB, très petite cardinalité (60000 objets au max, et surement pas plus de 1000 dans les listes), pas d'accès par index (rendu inutile par l'itérateur), Pas de Suppression (on vide tout d'un seul coup dans de rares cas)

    Comme je dois m'adapter à un code utilisant énormément de TList (qui boucle boucle et reboucle)
    Pour éviter certains boucles (récursives) ou requête SQL, je stockes les identifiants dans une liste et la seule fonction utile c'est valeur existe ou pas !

    Avec un vector, je dois faire un itérateur pour coder ma fonction Exists alors qu'un set, j'ai la méthode find (que j'encapsule pour des raisons de lisibilité)

    le terme de set me gène un peu, car j'ai l'habitude du Set de Delphi qui est plus proche d'un BitSet !
    Qu'en pensez-vous ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Seine Maritime (Haute Normandie)

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Points : 578
    Points
    578
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    au final, j'utilise assez peu le list<> mais beaucoup la TObjectList que j'ai encapsulé par des templates !
    Chez nous on utilise beaucoup des TList bricolés en templates, genre
    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
    template <class T> class TListT : public TList
    {
    private:
     
      T* __fastcall LireItem(int indice)
      {
        return (T*)Get(indice);
      }
     
      void __fastcall EcrireItem(int indice, T* pObjet)
      {
        Put(indice, pObjet);
      }
     
      public:
     
      T* __fastcall First(void)
      {
        return (T*)(TList::First());
      }
     
      T* __fastcall Last(void)
      {
        return (T*)(TList::Last());
      }
     
    //.... Idem IndexOf etc etc
     
      __property T* Items[int indice] = {read = LireItem, write=EcrireItem};
     
    };
     
    // Exemple:
    TListT<TForm>* pLst(new TListT<TForm>);
    for (int i=0; i<pLst->Count; i++)
      pLst->Items[i]->Show();
    Çà ne doit pas être très éloigné de ce que utilise, non ?

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    C'est tout à fait l'idée pour ne pas devoir re-déclarer tout à chaque fois !
    Pour le moment, ma template est minimal, j'ai encaspulé le minimum !
    Je n'ai pas eu le courage d'encapsuler toutes les fonctions de la TObjectList, en fait, j'ai juste modifie l'accesseur Items, ça doit être la seule chose je me sers !

    Comme je n'utilise quasiment que des TObject, j'utilise TObjectList !

    Je me suis demandé aussi pour TList<int> par exemple, de me faire ma propre générique
    Si j'ai bien compris, vouloir utilser la Generics.Collections.TList<> de BSD 2009 (ou plus) au lieu de la Classes.TListen C++ s'avère pénible ?!

    pour le moment, j'utilise la stl, d'où ma question sur les perfs de find() de set<int> par rapport à un iterator de list<int>, ce dernier revient à un IndexOf de la TList (sans tri, ça peut être long)

    L'avantage de la TObjectList c'est OwnObjects, je me préoccupe pas de libérer, Clear ou Free font le travail (un petit notify au besoin), ainsi je libère vide le Manager et lui libère collection et objets en cascade par le jeu de surcharge du destructor

    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
     
    //---------------------------------------------------------------------------
    //                         TCensureGenericObjectList                          -
    //---------------------------------------------------------------------------
    template<class T> // T doit hérité d'un TObject
    class TCensureGenericObjectList : public TObjectList
    {
    typedef TObjectList inherited;
     
      public:
      // Opérateurs Publiques
      T* operator[](int Index) { return Items[Index]; } // Cache TObjectList[]
     
    protected:
      // Accesseurs
      T* __fastcall GetItem(int Index) {return static_cast<T*>(inherited::Items[Index]);}
     
    public:
      // Propriétés Publiques
      __property T* Items[int Index] = {read=GetItem}; // default []
    };
    le static_cast me garanti que l'on utilise bien un TObject ou hérité de la VCL

    j'ai poussé le vice à refaire quasiment un Map mais C++ Builder semble ne pas apprécié trop de template dans __property !

    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
    //---------------------------------------------------------------------------
    //                    TCensureGenericObjectAssociationList                    -
    //---------------------------------------------------------------------------
    template<class T, class A> // T doit hérité d'un TObject, A n'a pas de restriction particulière
    class TCensureGenericObjectAssociationList : public TObjectList
    {
      typedef TObjectList inherited;
     
    public:
      // Opérateurs Publiques
      T* operator[](A AAssociation) { return GetItem(AAssociation); } // Cache TObjectList[]
     
    protected:
      // Accesseurs
      T* __fastcall GetItem(A AAssociation); // ! la liaison entre T et A doit être spécialisée
      T* __fastcall GetItemByIndex(int Index);
     
      // Méthodes Protégées
      int IndexOfAssociation(A AAssociation); // ! l'indexation de A doit être spécialisée
     
      // Propriétés Protégées
      __property T* ItemByIndex[int Index] = {read=GetItemByIndex};
     
    public:
      // Propriétés Publiques
      __property T* Items[A AAssociation] = {/*read=GetItem*/}; // default [] // See "Conseil et Rappel de Syntaxe"
    };
     
    //---------------------------------------------------------------------------
    /*                       Conseil et Rappel de Syntaxe                       -
    - Conflit __property\template :
    Items[] et GetItem ne peuvent pas être associé dans la template, il semble que le compilateur n'arrive pas à résoudre le type générique passé en paramètre
    Il est donc nécessaire de redéclarer Items dans chaque classe de spécialisation
    Erreur : Non concordance de paramètre dans le spécificateur d'accès 'read' de la propriété 'Items' (E2347)
     
    - Header :                                                                  -
    typedef TCensureGenericObjectAssociationList<Type1, Type2> TCensureClasseSpecialisationBaseTemplate;
    class TCensureClasseSpecialisation : public TCensureClasseSpecialisationBaseTemplate
    {                                                                           -
      // Ne pas oublier d'affecter les Accesseurs !
      __property Type1* Items[Type2 ParamName] = {read=GetItem}; // default []  -
    }                                                                           -
                                                                                -
    - Code :                                                                    -
    template<>                                                                  -
    Type1* __fastcall TCensureClasseSpecialisationBaseTemplate::GetItem(Type2 ParamName)...
                                                                               */
    //---------------------------------------------------------------------------
    A savoir que TCensureGenericObjectList et TCensureGenericObjectAssociationList ne sont rarement utilisé directement, je fais une classe héritée, je lui ajoute des méthodes "métiers" bien plus spécifique qu'un Add avec une sémantique différent comme Attach, Register, Associate ... en fait, je pourrais devrait même déclarer l'héritage en private (mais il semble qu'il ne faut pas le faire avec des objets VCL)

    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
    //---------------------------------------------------------------------------
    //                    TCensureVariableAnimationMasquageList                   -
    //             TCensureVariableAnimationMasquageListBaseTemplate              -
    //---------------------------------------------------------------------------
    typedef TCensureGenericObjectAssociationList<TCensureVariableAnimationMasquage, VARIABLE_SUPERVISION*> TCensureVariableAnimationMasquageListBaseTemplate;
    class TCensureVariableAnimationMasquageList : public TCensureVariableAnimationMasquageListBaseTemplate
    {
    private:
      // Membres Privés
      TCensureVariableAnimationMasquageDeleteEvent FOnVariableDelete;
     
      // Méthodes Privés
      void DoVariableDelete(UINT IDVariable);
     
    protected:
      // Méthodes Protégés
      /*override*/virtual void __fastcall Notify(void * Ptr, Classes::TListNotification Action);
     
    public:
      // Méthodes Publiques
      bool Attach(VARIABLE_SUPERVISION *ptrVariable, TCensureMDHList *AMDHList);
      void Detach(VARIABLE_SUPERVISION *ptrVariable);
     
      // Propriétés Publiques
      __property TCensureVariableAnimationMasquage* Items[VARIABLE_SUPERVISION *ptrVariable] = {read=GetItem}; // default []
      __property TCensureVariableAnimationMasquageDeleteEvent OnVariableDelete = {read=FOnVariableDelete, write=FOnVariableDelete};
    };
    Si j'étais moins flémard, en fait je devrais plutôt encapsuler mes TObjectList dans un Objet non liste qui possède les fonctions Add\Delete\Clear (avec la sémantique métier) et la propriété Items, juste ce qu'il faut !
    Car la on peut accéder à des méthodes non "templatées", et en réalité c'est mal !

    C'est comme cela que je fais en Delphi, je voulais surtout essayer les templates, c'était durant mon 1er mois en C++, durant ma phase de découverte du langage
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  10. #10
    Membre chevronné Avatar de nirgal76
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2007
    Messages
    905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

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

    Informations forums :
    Inscription : Septembre 2007
    Messages : 905
    Points : 2 127
    Points
    2 127
    Par défaut
    Pas gentil Totoche76, il ne t'as pas donné la version complète de notre TListT
    Celle-là permet de choisir lors de la création, si l'on désire ou non supprimer les éléments à la destruction de la liste.
    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
     
    template <class T, bool freeOnDelete=true>
    class TListT : public TList
    {
    public:
      __fastcall ~TListT()
      {
        if (freeOnDelete)
          Vider();
      }
     
      T* __fastcall First(void)
      {
        return reinterpret_cast<T*>(TList::First());
      }
     
      T* __fastcall Last(void)
      {
        return reinterpret_cast<T*>(TList::Last());
      }
     
      int __fastcall IndexOf(const T* pDonnee) const
      {
        return TList::IndexOf(const_cast<T*>(pDonnee));
      } 
     
      void __fastcall Vider(void)
      {
        for (int i=0; i<Count; ++i)
          delete Items[i];
        Clear();
      }
     
      __property T* Items[const int indiceItem] = {read = LireItem, write=EcrireItem};
     
    private:
      T* __fastcall LireItem(const int indiceItem) const
      {
        return reinterpret_cast<T*>(const_cast<TListT*>(this)->Get(indiceItem));
      }
      void __fastcall EcrireItem(const int indiceItem, T* pItem)
      {
        Put(indiceItem, pItem);
      } 
    };
    Pour les listes genre TList<int>, il y a TIntegerDynArray qui peut servir (il y en a pour un peu tous les types de base, TByteDynArray, TStringDynArray, TBoolDynArray etc...)

    Nirgal76

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Oui, TIntegerDynArray de l'unite Types.pas (sysdyn.h), je les connais bien, je les utilises au moins depuis Delphi 6 !

    J'ai hésité, mais comme je ne connaissais pas la STL et les génériques, j'en ai profité pour me "culturer", en plus set<int>.find c'est nettement plus pratique, je n'ai pas non plus besoin de faire des réallocations avec SetLength !

    Un petit FreeOnDelete, comme pour la TObjectList, et évidemment ne pas mettre à true si le type n'est pas un pointeur alloué par new !

    Merci Nirgal76 et Totoche76 !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. C++, STL, List et Iterator
    Par asgardia dans le forum SL & STL
    Réponses: 6
    Dernier message: 20/05/2007, 17h22
  2. STL list : acceder aux enfant d'une class depuis un liste
    Par poussinphp dans le forum SL & STL
    Réponses: 6
    Dernier message: 29/04/2007, 17h21
  3. pb dans la stl::list avec size
    Par DEVfan dans le forum SL & STL
    Réponses: 6
    Dernier message: 10/01/2007, 18h35
  4. STL List et variable globale (extern)
    Par flipper203 dans le forum SL & STL
    Réponses: 9
    Dernier message: 04/07/2006, 14h20
  5. STL : list
    Par hitchie dans le forum SL & STL
    Réponses: 17
    Dernier message: 02/04/2006, 21h44

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