Question sur le masquage de la structure interne des classes

Résolu
regitraz Messages postés 103 Statut Membre -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour,
voici deux screenshot d'un de mes cours de programmation en c++ et j'aimerai comprendre ce qui est fait sur la deuxieme image.
Le contexte : il s'agit de la création de la structure d'une liste doublement chainé (la cellule est donnée ailleur) :





Merci

1 réponse

  1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 943
     
    Bonjour,

    En C et en C++, il est possible de déclarer un type (sur la base d'un autre type).

    Exemples :
    typedef int toto_t;
    typedef int * pointeur_t;
    


    En C++, il est possible de déclarer un type à l'intérieur d'une classe ou d'une structure. C'est ce qui est fait avec :

    class Liste {
    ...
        typedef Cell * Place;
    ...
    }
    


    Ainsi, utiliser
    Place
    ou
    Cell *
    à l'intérieur de la classe
    Liste
    a le même sens.

    L'opérateur
    ::


    Comme le type
    Place
    est dans la classe, c'est un nom "relatif". Depuis l'extérieur de
    Liste
    il faut donc utiliser son nom absolu. Pour cela, le C++ a introduit (par rapport au C) un nouvel opérateur :
    ::
    . Celui-ci se comporte comme
    /
    pour un chemin. Sauf qu'au lieu d'écrire
    /Liste/Place
    on écrit
    ::Liste::Place
    ou plus simplement
    Liste::Place
    .

    L'opérateur
    ::
    s'applique aux classes, structures, mais aussi aux espaces de nommage (voir mot clé
    namespace
    ).

    Quel est l'intérêt ?

    Dans l'absolu, on sent qu'on aura besoin du type de la cellule par exemple dans la méthode qui retournera le i-ème élément de la liste. Sans
    typedef
    , cette méthode aurait les signatures :

    Cell * Liste::get(int i) const { ... }
    const Cell * Liste::get(int i) const { ... }
    


    On sent que ça n'est pas très élégant d'une part, et surtout si un jour on veut changer
    Cell
    par
    Cellule
    , cela impactera non seulement le code de
    Liste
    mais aussi tout le code qui utilise
    Liste
    . On voit alors que le fait d'utiliser
    Cell
    est un détail d'implémentation.

    En déclarant le type
    Place
    , on abstrait le code extérieur à
    Liste
    de ce détail, car la signatures deviennent :

    Place Liste::get(int i) const { ... }
    const Place Liste::get(int i) const { ... }
    


    On peut donc adapter l'implémentation de
    Liste::Place
    sans affecter le reste du code.

    Pour aller plus loin

    L'opérateur
    ::
    peut, à l'image de
    /
    , être enchaîné. Ainsi voici à quoi ressemble la liste standard du C++ :

    namespace std {
      template <typename T>
      class list {
        public:
          typedef ... iterator;
          typedef ... const_iterator;
        ...
      };
    }


    Ici on peut donc tout a fait parler de
    std::list<int>::iterator
    ou
    std::list<int>::const_iterator
    .

    Bonne chance
    0