Liste chainée et surcharge operator[]

Résolu
badboy38 Messages postés 95 Date d'inscription vendredi 14 janvier 2005 Statut Membre Dernière intervention 4 mars 2013 - 1 mars 2013 à 15:15
badboy38 Messages postés 95 Date d'inscription vendredi 14 janvier 2005 Statut Membre Dernière intervention 4 mars 2013 - 4 mars 2013 à 19:41
Bonjour à tous,

Voici mon problème: je développe une liste chainée et j'aimerai surcharger l'opérateur d'indexation pour accéder aux données.

Voici le header:

template <class T>
class Node {        // Noeud de la liste

    private:
        Node *next;         // Noeud précédent
        Node *prev;         // Noeud suivant

        T *data;            // Donnée

    public:
        Node( T data );                                // Constructeur simple, avec juste la donnée
        Node( T data, Node *prev, Node *next );        // Constructeur avec donnée, noeuds précédent et suivant
        ~Node();                                       // Destructeur, détruit la donnée stockés

        T GetData( bool remove);                       // Récupère la donnée
        Node* GetPrev();                               // Récupère le noeud précédent
        Node* GetNext();                               // Récupère le noeud suivant
        void SetPrev( Node *prev );                    // Assigne le noeud précédent (pour le tri)
        void SetNext( Node *next );                    // Assigne le noeud suivant (pour le tri)

        int Compare( Node *node );                     // Compare la donnée (impose que les opérateurs '<' et '>' au moins de T soit surchargés)
};

template <class T>
class List {        // La liste chainée

    private:
        CRITICAL_SECTION sync;     // Section critique de synchro
        int size;                  // Taille courante de la liste
        int maxsize;               // Taille max de la list

        Node<T> *head;             // Premier noeud
        Node<T> *tail;             // Dernier noeud

    public:
        List<T>( int maxsize );                      // Création avec taille max
        List<T>();                                   // Création sans taille max
        ~List();                                     // Destructeur, détruit aussi chaque noeud

        Node<T>* Add( T data );                      // Ajout d'un élément
        Node<T>* Add( T data, bool sortAsc );        // Ajout d'un élément ordonné (croissant / décroissant)
        void Remove( T data );                       // Enlève une donnée et détruit le noeud
        void Clear( );                               // Vide la liste sans la détruire

        int Size();                                  // Récupération de la taille
        void Sort( bool sortAsc );                   // Tri croissant / décroissant
        const T GetAt( int index );                  // Récupère la donnée à la "position" index

        /*const T& operator[] ( const int index ) const {        // Récupère la donnée à la "position" index
            return this->GetAt(index);
        }*/
};


Mon but est de remplacer la fonction List<T>::GetAt( int index) par l'opérateur [] pour pouvoir faire:

int main(int argc, char* argv[]) {
    List *intList = new List();
    List<double> doubleList();

    intList->Add( 1 );
    doubleList->Add( 3.14 );

    //cout << intList->GetAt(0) << endl;
    cout << intList[0] << endl;
    //cout << doubleList->GetAt(0) << endl;
    cout << doubleList[0] << endl;

    delete intList;

    return 0;



Quelqu'un pourrait il me dire comment déclarer la surcharge de l'opérateur [] car déclaré comme dans le header il provoque deux erreurs à la compilation:
main.cpp(7): error C2679: '<<' binaire: aucun opérateur trouvé qui accepte un opérande de partie droite de type 'List<T>' (...)
list.h(50): error C2662: 'List<T>::GetAt': impossible de convertir un pointeur 'this' de 'const List<T>' en 'const List<T> &' (...)


Par avance merci


BadBoy38
--
A voir également:

6 réponses

yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
1 mars 2013 à 21:19
Salut,

Dans le cas de ton premier code, si tu fait :
const T& operator[] ...

il faut que GetAt() renvoi une reférénce constante (const obj&)

puis pour l'utiliser :

cout << (*intList)[col] << endl;

bye...
3
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
1 mars 2013 à 16:13
Bonjour.

Normalement, ceci est censé être correct:

const T& operator[](int index) const
{
  return this->GetAt(index);
}
T& operator[](int index)
{
  return this->GetAt(index);
}


Ce qui ne va pas, c'est que tu ais ceci:
const T GetAt(int index);


Je mettrais plutôt:
T& GetAt(int index) const;
const T& GetAt(int index);


Ou alors n'utilise pas "GetAt" dans ton "operator[]".

Voici un exemple pour illustrer mes dires:
#include 

template <typename T>
class A
{
public:
  T& GetAt(int index)
  {
    return _tab[index];
  }

  const T& GetAt(int index) const
  {
    return _tab[index];
  }

  T& operator[](int index)
  {
    return GetAt(index);
    // ou
    // return _tab[index];
  }

  const T& operator[](int index) const
  {
    return GetAt(index);
    // ou
    // return _tab[index];
  }

private:
  int _tab[50];
};

int main()
{
  A a;

  a.GetAt(0) = 5;
  std::cout << a.GetAt(0) << std::endl;

  a[2] = 3;
  std::cout << a[2] << std::endl;

  return 0;
}



Quelques conseils.

Conceptuels:
Si tu développes ta propre liste chaînée pour apprendre, c'est une bonne démarche. Mais pour l'utilisation en production préfère une std::forwad_list (liste simplement chaînées) ou une std::list (liste doublement chaînées). Si tu rececherches une liste thread safe, mieux vaut poser un mutex par dessus une std::list ou alors utiliser une collection de TBB (intel threading building block), garantie robuste.

Techniques:
- Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- Un attribut de classe est différencié d'une variable par un signe distinctif (généralement on préfixe par "_")
- Il y a une subtilité du C++, dont beaucoup de gens tombe dedans. "List *intList = new List();" ne fait pas tout à fait ce que tu veux. En effet, pour instancier une classe en C++, on fait soit "new A;", soit "new A(arg1, arg2)". On ne fait jamais "new A();". "new A;" et "new A();" diffèrent. Le premier est correcte, le second, déclare une fonction anonyme vide, retournant un type A, que l'on instancie ! (Ce qui fonctionne au final, mais en passant pas la création d'une fonction inutile).
IL faut donc écrire:
List *intList = new List;
List<double> doubleList;
C'est très vicieux, et beaucoup se font avoir :)
- J'utiliserais "const T& data" plutôt que "T data". Tant que T est un type "pod" (simple), ça va. Mais si T est une classe, tu auras de nombreuses copies inutiles.
- "this->" n'est pas très utile en C++ et peut être omis.
- Met le maximum de constitude dès que tu le peux. Par exemple "int Compare(Node *node)" pourrait être plus sécurisé en mettant "int Compare(const Node* node) const".
- Pour les commentaires, évite de commenter "à côté" d'un code. Voir, http://0217021.free.fr/portfolio/axel.berardino/articles/ecrire-de-bons-commentaires


________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
1
badboy38 Messages postés 95 Date d'inscription vendredi 14 janvier 2005 Statut Membre Dernière intervention 4 mars 2013
1 mars 2013 à 16:58
Merci pour l'extrait de code, je teste ça et je reviens pour donner les résultats.

Et un grand merci pour tout ces commentaires et ces conseils! (même si certains n'étaient pas nécessaire, vu que j'ai mis là un code "épuré") merci beaucoup.


BadBoy38
--
0
badboy38 Messages postés 95 Date d'inscription vendredi 14 janvier 2005 Statut Membre Dernière intervention 4 mars 2013
1 mars 2013 à 17:56
Bon, pas moyen... ça veut pas...

Du coup, j'ai fait un itérateur. C'est pas un drame, le but de ce dev est de redécouvrir le C++, ça doit faire 10 ans que j'en ai pas fait! Mais je retiens tes conseils, ça va m'aider à m'améliorer

Merci.

BadBoy38
--
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
1 mars 2013 à 18:07
Bon, pas moyen... ça veut pas...
Du coup, j'ai fait un itérateur. C'est pas un drame,

Comme tu veux. Mais si tu me copies tout, en un seul fichier compilable sur codepad.org, je peux jeter un coup d'oeil :)

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
0
badboy38 Messages postés 95 Date d'inscription vendredi 14 janvier 2005 Statut Membre Dernière intervention 4 mars 2013
4 mars 2013 à 19:41
En effet, ça marche!!
C'est un peu dommage pour le déréférencement à l'utilisation, mais que du bon!

merci ;)

BadBoy38
--
0
Rejoignez-nous