Fonctions membres const
Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 29 sur 104.
Vous avez vu le mot-clé const sur les méthodes getter dans la leçon précédente. Mais que signifie exactement la présence de const après la liste des paramètres d’une fonction ? Une fonction membre const promet de ne modifier aucune variable membre de l’objet.
class Rectangle {
int width;
int height;
public:
Rectangle(int w, int h) : width(w), height(h) {}
int getArea() const { // fonction membre const
return width * height; // La lecture des membres est autorisée
}
void setWidth(int w) { // Non-const - modifie l'objet
width = w;
}
};Le const après la liste des paramètres indique au compilateur : « Cette fonction ne modifiera pas l’état de l’objet. » Si vous essayez de modifier une variable membre à l’intérieur d’une fonction const, le compilateur produira une erreur.
Cela devient essentiel lorsque vous travaillez avec des objets const ou des références const. Un objet const ne peut appeler que des fonctions membres const :
void printArea(const Rectangle& rect) {
std::cout << rect.getArea(); // OK - getArea() est const
// rect.setWidth(10); // ERREUR - setWidth() n'est pas const
}Marquer les fonctions comme const lorsqu’elles ne modifient pas l’objet est une bonne pratique. Cela documente votre intention, permet à la fonction de fonctionner avec des objets const et aide le compilateur à détecter les modifications accidentelles. Toute fonction membre qui se contente de lire des données doit être marquée const.
Défi
FacileConstruisons un convertisseur de température qui montre quand et pourquoi utiliser des fonctions membres const. Vous allez créer une classe dont certaines méthodes se contentent de lire les données (et doivent donc être const), tandis que d'autres modifient l'état de l'objet.
Vous allez créer deux fichiers pour organiser votre code :
Temperature.h: définissez une classeTemperaturequi stocke une valeur de température et fournit différentes façons de la lire et de la modifier. Votre classe doit comporter :- Un membre privé
celsius(double) pour stocker la température - Un constructeur qui prend une valeur initiale en degrés Celsius
- Une méthode
getCelsius()qui renvoie la valeur stockée. Elle doit être const puisqu'elle ne fait que lire les données - Une méthode
getFahrenheit()qui calcule et renvoie la température en degrés Fahrenheit à l'aide de la formulecelsius * 9.0 / 5.0 + 32.0, également const puisqu'elle ne modifie rien - Une méthode
getKelvin()qui renvoie la température en kelvins à l'aide decelsius + 273.15: elle doit également être const - Une méthode
setCelsius(double value)qui met à jour la température stockée. Elle ne peut pas être const puisqu'elle modifie l'objet - Une méthode
adjustBy(double delta)qui ajoute le delta à la température actuelle, elle aussi non const
- Un membre privé
main.cpp: montrez comment fonctionnent les fonctions membres const avec des objets ordinaires et des objets const. Lisez une valeur de température initiale depuis l'entrée, puis :- Créez un objet
Temperatureavec la valeur saisie - Affichez
"Initial: <celsius>C = <fahrenheit>F = <kelvin>K" - Ajustez la température de
10.0degrés - Affichez
"After adjustment: <celsius>C" - Créez une fonction auxiliaire
void printReadings(const Temperature& temp)qui prend une référence const et affiche"Reading: <celsius>C, <fahrenheit>F". Cette fonction ne peut appeler que des méthodes const sur temp - Appelez
printReadings()avec votre objet de température - Réglez la température sur
0.0(point de congélation) - Affichez
"Freezing point: <celsius>C = <fahrenheit>F"
- Créez un objet
Formatez toutes les valeurs de température avec une décimale à l'aide de std::fixed et std::setprecision(1) provenant de <iomanip>.
L'idée essentielle ici est que printReadings() reçoit une référence const ; elle ne peut donc appeler que des méthodes marquées comme const. C'est pourquoi il est important de marquer correctement vos méthodes d'accès comme const. Cela leur permet de fonctionner dans des contextes où l'objet ne peut pas être modifié.
Essayez vous-même
#include <iostream>
#include <iomanip>
#include "Temperature.h"
using namespace std;
// TODO: Implémenter les méthodes de la classe Temperature ici
// Constructeur
Temperature::Temperature(double initialCelsius) {
// TODO: Initialiser celsius
}
// TODO: Implémenter getCelsius() en tant que const
// TODO: Implémenter getFahrenheit() en tant que const
// TODO: Implémenter getKelvin() en tant que const
// TODO: Implémenter setCelsius(double value)
// TODO: Implémenter adjustBy(double delta)
// TODO: Créer une fonction d'aide printReadings qui prend un const Temperature&
// et affiche "Reading: <celsius>C, <fahrenheit>F"
// Note: Cette fonction ne peut appeler que des méthodes const sur temp !
int main() {
double initialTemp;
cin >> initialTemp;
// Définir le formatage de la sortie
cout << fixed << setprecision(1);
// TODO: Créer un objet Temperature avec la valeur d'entrée
// TODO: Afficher "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"
// TODO: Ajuster la température de 10.0 degrés
// TODO: Print "After adjustment: <celsius>C"
// TODO: Appeler printReadings() avec votre objet temperature
// TODO: Set the temperature to 0.0 (freezing point)
// TODO: Print "Freezing point: <celsius>C = <fahrenheit>F"
return 0;
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesGénération et compilation en C++Fichiers d’en-tête et fichiers sourceEspaces de noms et portéeIntroduction à la POO en C++Classes et objetsLe pointeur « this »Méthodes (fonctions membres)Attributs (membres de données)Bases des constructeurs et destructeursRécapitulatif - Calculatrice simple4Propriétés de classe
Membres d’instance et statiquesAccesseurs et mutateursFonctions membres constMot-clé mutableMéthodes et variables statiquesFonctions et classes amiesRécapitulatif - Gestionnaire de compte bancaire7Héritage
Héritage de baseNiveaux d’accès de l’héritageOrdre d’appel des constructeurs et destructeursRedéfinition des méthodesFonctions virtuelles et VTableHéritage multipleHéritage virtuelRécapitulatif : hiérarchie des employés10Vue d’ensemble de la STL
Vue d’ensemble et philosophie de la STLConteneurs de la STLItérateursAlgorithmes de la STLFoncteurs et expressions lambdaRécapitulatif - fréquence des mots13Modèles de conception, partie 1
Introduction aux modèles de conceptionModèle SingletonFabrique et fabrique abstraiteModèle BuilderModèle ObserverModèle Strategy2Gestion de la mémoire
Mémoire de pile ou de tasPointeurs et référencesMémoire dynamique (new/delete)Pointeurs intelligents en C++RAII en C++Récapitulatif - Gestionnaire de tableaux dynamiques5Encapsulation
Spécificateurs d’accès en C++Spécificateurs d’accès en profondeurMasquage de l’informationStruct vs classeClasses imbriquées et internesRécapitulatif - Système de gestion des dossiers étudiants8Polymorphisme
Polymorphisme à la compilation vs à l’exécutionSurcharge de fonctionsRetour sur les fonctions virtuellesFonctions virtuelles puresClasses abstraitesConception d’interfaces en C++Conversion dynamique et RTTIRécapitulatif - Calculateur de formes3Constructeurs et destructeurs
Constructeur par défautConstructeur paramétréConstructeur de copieConstructeur de déplacementListes d’initialisation des constructeursConstructeurs déléguésApprofondissement des destructeursRègle des trois / cinq / zéroRécapitulatif - Classe String6Surcharge des opérateurs
Introduction à la surcharge des opérateursSurcharge des opérateurs arithmétiquesSurcharge des opérateurs de comparaisonOpérateurs de fluxSurcharge de l’opérateur d’affectationSurcharge des opérateurs [] et ()Opérateurs de conversion de typeRécapitulatif – Classe Matrix9Templates
Templates de fonctionsTemplates de classesSpécialisation des templatesTemplates variadiquesBases de SFINAE et des traits de typesRécapitulatif - Conteneur génériqueEntraînez-vous par vous-même : Compilateur C++ en ligne