# Programmation C-C++/C++ : La couche objet/Pointeurs sur les membres d'une classe

Cours de C/C++ :
| C++ : La couche objet ||
| | Généralités |
| | Extension de la notion de type du C |
| | Déclaration de classes en C++ |
| | Encapsulation des données |
| | Héritage |
| | Classes virtuelles |
| | Fonctions et classes amies |
| | Constructeurs et destructeurs |
| | Pointeur this |
| | Données et fonctions membres statiques |
| | Surcharge des opérateurs |
| | Des entrées - sorties simplifiées |
| | Méthodes virtuelles |
| | Dérivation |
| | Méthodes virtuelles pures - Classes abstraites |
| | Pointeurs sur les membres d'une classe |
| Livre original de C. Casteyde ||
Nous avons déjà vu les pointeurs sur les objets. Il nous reste à voir les pointeurs sur les membres des classes.
Les classes regroupent les caractéristiques des données et des fonctions des objets. Les membres des classes ne peuvent donc pas être manipulés sans passer par la classe à laquelle ils appartiennent. Par conséquent, il faut, lorsqu'on veut faire un pointeur sur un membre, indiquer le nom de sa classe. Pour cela, la syntaxe suivante est utilisée :
Par exemple, si une classe test contient des entiers, le type de pointeurs à utiliser pour stocker leur adresse est :
Si on veut déclarer un pointeur p de ce type, on écrira donc :
Une fois le pointeur déclaré, on pourra l'initialiser en prenant l'adresse du membre de la classe du type correspondant. Pour cela, il faudra encore spécifier le nom de la classe avec l'opérateur de résolution de portée :
La même syntaxe est utilisable pour les fonctions. L'emploi d'un typedef est dans ce cas fortement recommandé. Par exemple, si la classe test dispose d'une fonction membre appelée lit, qui n'attend aucun paramètre et qui renvoie un entier, on pourra récupérer son adresse ainsi :
Cependant, ces pointeurs ne sont pas utilisables directement. En effet, les données d'une classe sont instanciées pour chaque objet, et les fonctions membres reçoivent systématiquement le pointeur this sur l'objet de manière implicite. On ne peut donc pas faire un déréférencement direct de ces pointeurs. Il faut spécifier l'objet pour lequel le pointeur va être utilisé. Cela se fait avec la syntaxe suivante :
Pour les pointeurs d'objet, on pourra utiliser l'opérateur ->* à la place de l'opérateur .* (appelé pointeur sur opérateur de sélection de membre).
Ainsi, si a est un objet de classe test, on pourra accéder à la donnée i de cet objet à travers le pointeur p1 avec la syntaxe suivante :
Pour les fonctions membres, on mettra des parenthèses à cause des priorités des opérateurs :
Pour les données et les fonctions membres statiques, cependant, la syntaxe est différente. En effet, les données n'appartiennent plus aux objets de la classe, mais à la classe elle-même, et il n'est plus nécessaire de connaître l'objet auquel le pointeur s'applique pour les utiliser. De même, les fonctions membres statiques ne reçoivent pas le pointeur sur l'objet, et on peut donc les appeler sans référencer ce dernier.
La syntaxe s'en trouve donc modifiée. Les pointeurs sur les membres statiques des classes sont compatibles avec les pointeurs sur les objets et les fonctions non-membres. Par conséquent, si une classe contient une donnée statique entière, on pourra récupérer son adresse directement et la mettre dans un pointeur d'entier :
La même syntaxe s'appliquera pour les fonctions :
Enfin, l'utilisation des ces pointeurs est identique à celle des pointeurs classiques, puisqu'il n'est pas nécessaire de fournir le pointeur this. Il est donc impossible de spécifier le pointeur sur l'objet sur lequel la fonction doit travailler aux fonctions membres statiques. Cela est naturel, puisque les fonctions membres statiques ne peuvent pas accéder aux données non statiques d'une classe.