--- title: "Accesseurs et mutateurs en C++ : getters et setters expliqués" url: https://www.dico-micro.com/langage-c-accesseurs-et-mutateurs/ author: "Dico Micro" date_published: 2023-07-01T14:09:06+00:00 date_modified: 2026-09-26T16:32:35+00:00 categories: ["Actus high-tech"] image: https://www.dico-micro.com/wp-content/uploads/2026/09/langage-c-accesseurs-et-mutateurs.jpg description: "En C++, les accesseurs lisent une donnée membre privée et les mutateurs la modifient, ce qui permet de vérifier chaque valeur avant de l'accepter dans l'objet." site: "Dico Micro" license: "Reproduction autorisée avec lien vers la source." --- # Accesseurs et mutateurs en C++ : getters et setters expliqués > En C++, les accesseurs lisent une donnée membre privée et les mutateurs la modifient, ce qui permet de vérifier chaque valeur avant de l'accepter dans l'objet. Une classe C++ garde le contrôle total sur ses données membres déclarées *private* : seules ses propres fonctions membres peuvent les lire ou les modifier. Deux types de fonctions se chargent de cet accès : les accesseurs pour lire, les mutateurs pour écrire. Ce mécanisme porte un nom savant, l’encapsulation, mais l’idée derrière est simple : c’est vous, en tant qu’auteur de la classe, qui décidez comment vos données peuvent être lues ou changées, plutôt que de laisser n’importe quel morceau de code du programme y toucher directement. ## Pourquoi cacher une donnée membre Une donnée membre *private* reste invisible depuis l’extérieur de la classe : aucune autre partie du programme ne peut la lire ou l’écrire sans passer par une fonction que vous avez vous-même écrite. Deux catégories de fonctions remplissent ce rôle : - les **accesseurs**, aussi appelés *getters*, qui renvoient la valeur d’une donnée membre ; - les **mutateurs**, aussi appelés *setters*, qui modifient cette valeur. **Ce que change l’encapsulation** Sans accesseur ni mutateur, n’importe quelle fonction du programme peut modifier directement une donnée membre publique, y compris avec une valeur absurde. En passant par des fonctions dédiées, vous gardez le contrôle sur ce qui est autorisé. ## L’accesseur : lire une donnée protégée Un accesseur doit renvoyer le type de la donnée qu’il expose, et n’a en général pas besoin d’argument. La convention veut qu’on le nomme en commençant par *Get*, pour que sa fonction saute aux yeux dès la lecture du code. Réduit à sa plus simple expression, il ressemble à ceci pour une donnée membre nommée *age* : | Déclaration dans la classe | Définition de la fonction | | --- | --- | | private : int age ; public : int GetAge() ; | int Toto::GetAge() { return age ; } | Cette fonction ne fait rien d’autre que renvoyer la valeur stockée. C’est volontaire : un accesseur sert à lire, pas à transformer la donnée au passage. ## Le mutateur : modifier une donnée protégée Un mutateur reçoit en paramètre la valeur à assigner, du même type que la donnée membre concernée, et ne renvoie généralement rien (type *void*). La convention de nommage veut qu’on le préfixe par *Set*. Sur le même exemple, un mutateur minimal ressemble à ceci : | Déclaration dans la classe | Définition de la fonction | | --- | --- | | private : int _age ; public : void SetAge(int) ; | void Toto::SetAge(int age) { _age = age ; } | **Pourquoi préfixer différemment la donnée et le paramètre** Nommer la donnée membre *_age* et le paramètre *age* évite toute ambiguïté dans le corps de la fonction : le compilateur, et surtout la personne qui relit le code plus tard, sait immédiatement lequel des deux est modifié. ## Le vrai intérêt d’un mutateur : contrôler la valeur avant de l’accepter L’avantage d’un mutateur ne tient pas seulement à l’encapsulation : c’est l’endroit idéal pour vérifier qu’une valeur est acceptable avant de l’assigner. Un âge ne devrait jamais être négatif, ni dépasser une limite raisonnable ; le mutateur peut tester cette condition et refuser l’affectation si elle n’est pas respectée, plutôt que de laisser une donnée incohérente s’installer silencieusement dans l’objet : | Version avec contrôle | Comportement | | --- | --- | | int Toto::SetAge(int age) { if (age < ; 200) { _age = age ; return 1 ; } else return 0 ; } | Renvoie 1 si la valeur a été acceptée, 0 sinon, sans jamais modifier *_age* avec une valeur jugée invalide. | **Un contrôle qui se pose une fois, à un seul endroit** Sans mutateur, la même vérification devrait être recopiée à chaque endroit du programme qui modifie la donnée, avec le risque d’en oublier une. Centralisée dans le mutateur, elle s’applique automatiquement partout où la classe est utilisée. ## Le piège d’une encapsulation seulement apparente Un accesseur ou un mutateur mal écrit peut donner une fausse impression de sécurité. Un accesseur qui renvoie directement une référence vers une donnée interne complexe, par exemple, permet en réalité de la modifier de l’extérieur sans passer par le mutateur, ce qui annule tout l’intérêt de l’encapsulation. La règle reste simple : un accesseur renvoie une copie ou une valeur en lecture seule, un mutateur passe par un test avant d’accepter le changement. C’est cette discipline, plus que la simple présence de *Get* et *Set* dans le nom des fonctions, qui fait la différence entre une classe bien conçue et une classe qui ne fait que déplacer le problème d’un mot-clé *private* vers un autre. Ce mécanisme fait partie des bases de la [programmation par objets](https://www.dico-micro.com/glossaire/p/#programmation-par-objets), aux côtés de l’héritage et du polymorphisme, et se retrouve avec des noms et des syntaxes différentes dans la quasi-totalité des langages orientés objet, de Java à Python en passant par C#. --- ## À propos de l'auteur **Dico Micro** — La rédaction de Dico Micro : matériel, logiciels et culture geek, expliqués sans jargon.