Liste chainée et surcharge operator[] [Résolu]

Messages postés
95
Date d'inscription
vendredi 14 janvier 2005
Dernière intervention
4 mars 2013
- 1 mars 2013 à 15:15 - Dernière réponse :
Messages postés
95
Date d'inscription
vendredi 14 janvier 2005
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
--
Afficher la suite 

Votre réponse

6 réponses

Meilleure réponse
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Dernière intervention
23 janvier 2016
- 1 mars 2013 à 21:19
3
Merci
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...

Merci yann_lo_san 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 88 internautes ce mois-ci

Commenter la réponse de yann_lo_san
Messages postés
3829
Date d'inscription
dimanche 12 décembre 2004
Dernière intervention
5 novembre 2018
- 1 mars 2013 à 16:13
0
Merci
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
Commenter la réponse de cptpingu
Messages postés
95
Date d'inscription
vendredi 14 janvier 2005
Dernière intervention
4 mars 2013
- 1 mars 2013 à 16:58
0
Merci
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
--
Commenter la réponse de badboy38
Messages postés
95
Date d'inscription
vendredi 14 janvier 2005
Dernière intervention
4 mars 2013
- 1 mars 2013 à 17:56
0
Merci
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
--
Commenter la réponse de badboy38
Messages postés
3829
Date d'inscription
dimanche 12 décembre 2004
Dernière intervention
5 novembre 2018
- 1 mars 2013 à 18:07
0
Merci
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
Commenter la réponse de cptpingu
Messages postés
95
Date d'inscription
vendredi 14 janvier 2005
Dernière intervention
4 mars 2013
- 4 mars 2013 à 19:41
0
Merci
En effet, ça marche!!
C'est un peu dommage pour le déréférencement à l'utilisation, mais que du bon!

merci ;)

BadBoy38
--
Commenter la réponse de badboy38

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.