[{"data":1,"prerenderedAt":887},["ShallowReactive",2],{"page-\u002Fcpp\u002Fclasses-et-raii":3,"pieces-cpp":844,"autour-\u002Fcpp\u002Fclasses-et-raii":869,"prerequis-\u002Fcpp\u002Fclasses-et-raii":874,"plan-cpp":876},{"id":4,"title":5,"body":6,"description":816,"extension":817,"ligne":46,"meta":818,"motsCles":819,"navigation":77,"niveau":821,"path":822,"prerequis":823,"ressources":825,"seo":834,"sources":835,"stem":842,"__hash__":843},"docs\u002Fcpp\u002F05.classes-et-raii.md","Classes, constructeurs et RAII",{"type":7,"value":8,"toc":806},"minimark",[9,14,27,31,40,213,220,224,234,334,348,363,367,374,472,487,490,512,516,526,640,643,647,653,719,730,744,748,762,769,773,802],[10,11,13],"h2",{"id":12},"ce-que-tu-vas-apprendre","Ce que tu vas apprendre",[15,16,17,21,24],"ul",{},[18,19,20],"li",{},"Écrire une classe avec des données privées et des méthodes publiques.",[18,22,23],{},"Initialiser un objet avec un constructeur.",[18,25,26],{},"Comprendre le destructeur et le principe RAII.",[10,28,30],{"id":29},"une-première-classe","Une première classe",[32,33,34,35,39],"p",{},"Une ",[36,37,38],"strong",{},"classe"," décrit un nouveau type qui regroupe des données et les fonctions qui les manipulent. Un objet est une instance de cette classe.",[41,42,48],"pre",{"className":43,"code":44,"filename":45,"language":46,"meta":47,"style":47},"language-cpp shiki shiki-themes github-light-default github-dark-default github-dark-default","#include \u003Ciostream>\n#include \u003Cstring>\n\nclass Recette {\npublic:\n    std::string titre;\n    int minutes;\n};\n\nint main() {\n    Recette r{\"Crêpes\", 20};\n    std::cout \u003C\u003C r.titre \u003C\u003C \" : \" \u003C\u003C r.minutes \u003C\u003C \" min\\n\";\n}\n","recette.cpp","cpp","",[49,50,51,64,72,79,93,99,114,123,129,134,147,168,207],"code",{"__ignoreMap":47},[52,53,56,60],"span",{"class":54,"line":55},"line",1,[52,57,59],{"class":58},"sOnC1","#include",[52,61,63],{"class":62},"shWOn"," \u003Ciostream>\n",[52,65,67,69],{"class":54,"line":66},2,[52,68,59],{"class":58},[52,70,71],{"class":62}," \u003Cstring>\n",[52,73,75],{"class":54,"line":74},3,[52,76,78],{"emptyLinePlaceholder":77},true,"\n",[52,80,82,85,89],{"class":54,"line":81},4,[52,83,84],{"class":58},"class",[52,86,88],{"class":87},"sIXEE"," Recette",[52,90,92],{"class":91},"scfrF"," {\n",[52,94,96],{"class":54,"line":95},5,[52,97,98],{"class":58},"public:\n",[52,100,102,105,108,111],{"class":54,"line":101},6,[52,103,104],{"class":87},"    std",[52,106,107],{"class":91},"::",[52,109,110],{"class":87},"string",[52,112,113],{"class":91}," titre;\n",[52,115,117,120],{"class":54,"line":116},7,[52,118,119],{"class":58},"    int",[52,121,122],{"class":91}," minutes;\n",[52,124,126],{"class":54,"line":125},8,[52,127,128],{"class":91},"};\n",[52,130,132],{"class":54,"line":131},9,[52,133,78],{"emptyLinePlaceholder":77},[52,135,137,140,144],{"class":54,"line":136},10,[52,138,139],{"class":58},"int",[52,141,143],{"class":142},"syCW7"," main",[52,145,146],{"class":91},"() {\n",[52,148,150,153,156,159,162,166],{"class":54,"line":149},11,[52,151,152],{"class":87},"    Recette",[52,154,155],{"class":91}," r{",[52,157,158],{"class":62},"\"Crêpes\"",[52,160,161],{"class":91},", ",[52,163,165],{"class":164},"s5iOY","20",[52,167,128],{"class":91},[52,169,171,173,176,179,182,184,187,190,193,195,198,201,204],{"class":54,"line":170},12,[52,172,104],{"class":87},[52,174,175],{"class":91},"::cout ",[52,177,178],{"class":58},"\u003C\u003C",[52,180,181],{"class":91}," r.titre ",[52,183,178],{"class":58},[52,185,186],{"class":62}," \" : \"",[52,188,189],{"class":58}," \u003C\u003C",[52,191,192],{"class":91}," r.minutes ",[52,194,178],{"class":58},[52,196,197],{"class":62}," \" min",[52,199,200],{"class":58},"\\n",[52,202,203],{"class":62},"\"",[52,205,206],{"class":91},";\n",[52,208,210],{"class":54,"line":209},13,[52,211,212],{"class":91},"}\n",[32,214,215,216,219],{},"Le mot ",[49,217,218],{},"public"," rend les membres accessibles depuis l'extérieur. Les valeurs entre accolades initialisent les membres dans l'ordre de déclaration.",[10,221,223],{"id":222},"encapsulation","Encapsulation",[32,225,226,227,229,230,233],{},"Laisser les données publiques permet à n'importe qui de les mettre dans un état absurde (une durée négative, par exemple). L'",[36,228,222],{}," consiste à les rendre ",[49,231,232],{},"private"," et à passer par des méthodes :",[41,235,237],{"className":43,"code":236,"language":46,"meta":47,"style":47},"class Recette {\npublic:\n    int minutes() const { return minutes_; }\n    void rallonger(int extra) { minutes_ += extra; }\n\nprivate:\n    std::string titre_;\n    int minutes_{0};\n};\n",[49,238,239,247,251,273,298,302,307,318,330],{"__ignoreMap":47},[52,240,241,243,245],{"class":54,"line":55},[52,242,84],{"class":58},[52,244,88],{"class":87},[52,246,92],{"class":91},[52,248,249],{"class":54,"line":66},[52,250,98],{"class":58},[52,252,253,255,258,261,264,267,270],{"class":54,"line":74},[52,254,119],{"class":58},[52,256,257],{"class":142}," minutes",[52,259,260],{"class":91},"() ",[52,262,263],{"class":58},"const",[52,265,266],{"class":91}," { ",[52,268,269],{"class":58},"return",[52,271,272],{"class":91}," minutes_; }\n",[52,274,275,278,281,284,286,289,292,295],{"class":54,"line":81},[52,276,277],{"class":58},"    void",[52,279,280],{"class":142}," rallonger",[52,282,283],{"class":91},"(",[52,285,139],{"class":58},[52,287,288],{"class":87}," extra",[52,290,291],{"class":91},") { minutes_ ",[52,293,294],{"class":58},"+=",[52,296,297],{"class":91}," extra; }\n",[52,299,300],{"class":54,"line":95},[52,301,78],{"emptyLinePlaceholder":77},[52,303,304],{"class":54,"line":101},[52,305,306],{"class":58},"private:\n",[52,308,309,311,313,315],{"class":54,"line":116},[52,310,104],{"class":87},[52,312,107],{"class":91},[52,314,110],{"class":87},[52,316,317],{"class":91}," titre_;\n",[52,319,320,322,325,328],{"class":54,"line":125},[52,321,119],{"class":58},[52,323,324],{"class":91}," minutes_{",[52,326,327],{"class":164},"0",[52,329,128],{"class":91},[52,331,332],{"class":54,"line":131},[52,333,128],{"class":91},[32,335,336,337,339,340,343,344,347],{},"Le ",[49,338,263],{}," après ",[49,341,342],{},"minutes()"," promet que la méthode ne modifie pas l'objet. Le suffixe ",[49,345,346],{},"_"," sur les membres privés est une convention répandue, pas une obligation.",[349,350,351],"note",{},[32,352,353,356,357,359,360,362],{},[49,354,355],{},"struct"," est une classe dont les membres sont publics par défaut, alors que pour ",[49,358,84],{}," ils sont privés. On réserve souvent ",[49,361,355],{}," aux simples regroupements de données.",[10,364,366],{"id":365},"le-constructeur","Le constructeur",[32,368,369,370,373],{},"Un ",[36,371,372],{},"constructeur"," est une fonction spéciale appelée à la création de l'objet. Il porte le nom de la classe et n'a pas de type de retour :",[41,375,377],{"className":43,"code":376,"language":46,"meta":47,"style":47},"class Recette {\npublic:\n    Recette(std::string titre, int minutes)\n        : titre_{std::move(titre)}, minutes_{minutes} {}\n\nprivate:\n    std::string titre_;\n    int minutes_;\n};\n",[49,378,379,387,391,416,443,447,451,461,468],{"__ignoreMap":47},[52,380,381,383,385],{"class":54,"line":55},[52,382,84],{"class":58},[52,384,88],{"class":87},[52,386,92],{"class":91},[52,388,389],{"class":54,"line":66},[52,390,98],{"class":58},[52,392,393,395,397,400,402,404,407,409,411,413],{"class":54,"line":74},[52,394,152],{"class":142},[52,396,283],{"class":91},[52,398,399],{"class":87},"std",[52,401,107],{"class":91},[52,403,110],{"class":87},[52,405,406],{"class":87}," titre",[52,408,161],{"class":91},[52,410,139],{"class":58},[52,412,257],{"class":87},[52,414,415],{"class":91},")\n",[52,417,418,421,424,427,429,431,434,437,440],{"class":54,"line":81},[52,419,420],{"class":91},"        : ",[52,422,423],{"class":142},"titre_",[52,425,426],{"class":91},"{",[52,428,399],{"class":87},[52,430,107],{"class":91},[52,432,433],{"class":142},"move",[52,435,436],{"class":91},"(titre)}, ",[52,438,439],{"class":142},"minutes_",[52,441,442],{"class":91},"{minutes} {}\n",[52,444,445],{"class":54,"line":95},[52,446,78],{"emptyLinePlaceholder":77},[52,448,449],{"class":54,"line":101},[52,450,306],{"class":58},[52,452,453,455,457,459],{"class":54,"line":116},[52,454,104],{"class":87},[52,456,107],{"class":91},[52,458,110],{"class":87},[52,460,317],{"class":91},[52,462,463,465],{"class":54,"line":125},[52,464,119],{"class":58},[52,466,467],{"class":91}," minutes_;\n",[52,469,470],{"class":54,"line":131},[52,471,128],{"class":91},[32,473,474,475,478,479,482,483,486],{},"La partie après les deux-points est la ",[36,476,477],{},"liste d'initialisation"," : elle construit chaque membre directement avec la bonne valeur. ",[49,480,481],{},"std::move"," demande le déplacement de la chaîne au lieu de sa copie ; il faut ",[49,484,485],{},"#include \u003Cutility>"," pour l'utiliser.",[32,488,489],{},"Création d'un objet :",[41,491,493],{"className":43,"code":492,"language":46,"meta":47,"style":47},"Recette r{\"Tarte tatin\", 60};\n",[49,494,495],{"__ignoreMap":47},[52,496,497,500,502,505,507,510],{"class":54,"line":55},[52,498,499],{"class":87},"Recette",[52,501,155],{"class":91},[52,503,504],{"class":62},"\"Tarte tatin\"",[52,506,161],{"class":91},[52,508,509],{"class":164},"60",[52,511,128],{"class":91},[10,513,515],{"id":514},"le-destructeur","Le destructeur",[32,517,336,518,521,522,525],{},[36,519,520],{},"destructeur"," s'exécute automatiquement quand l'objet disparaît, c'est-à-dire en fin de bloc pour une variable locale. Il se note ",[49,523,524],{},"~NomDeLaClasse"," :",[41,527,529],{"className":43,"code":528,"language":46,"meta":47,"style":47},"class Journal {\npublic:\n    Journal()  { std::cout \u003C\u003C \"Ouverture\\n\"; }\n    ~Journal() { std::cout \u003C\u003C \"Fermeture\\n\"; }\n};\n\nint main() {\n    Journal j;\n    std::cout \u003C\u003C \"Travail en cours\\n\";\n}   \u002F\u002F affiche « Fermeture » ici\n",[49,530,531,540,544,568,591,595,599,607,614,631],{"__ignoreMap":47},[52,532,533,535,538],{"class":54,"line":55},[52,534,84],{"class":58},[52,536,537],{"class":87}," Journal",[52,539,92],{"class":91},[52,541,542],{"class":54,"line":66},[52,543,98],{"class":58},[52,545,546,549,552,554,556,558,561,563,565],{"class":54,"line":74},[52,547,548],{"class":142},"    Journal",[52,550,551],{"class":91},"()  { ",[52,553,399],{"class":87},[52,555,175],{"class":91},[52,557,178],{"class":58},[52,559,560],{"class":62}," \"Ouverture",[52,562,200],{"class":58},[52,564,203],{"class":62},[52,566,567],{"class":91},"; }\n",[52,569,570,573,576,578,580,582,585,587,589],{"class":54,"line":81},[52,571,572],{"class":142},"    ~Journal",[52,574,575],{"class":91},"() { ",[52,577,399],{"class":87},[52,579,175],{"class":91},[52,581,178],{"class":58},[52,583,584],{"class":62}," \"Fermeture",[52,586,200],{"class":58},[52,588,203],{"class":62},[52,590,567],{"class":91},[52,592,593],{"class":54,"line":95},[52,594,128],{"class":91},[52,596,597],{"class":54,"line":101},[52,598,78],{"emptyLinePlaceholder":77},[52,600,601,603,605],{"class":54,"line":116},[52,602,139],{"class":58},[52,604,143],{"class":142},[52,606,146],{"class":91},[52,608,609,611],{"class":54,"line":125},[52,610,548],{"class":87},[52,612,613],{"class":91}," j;\n",[52,615,616,618,620,622,625,627,629],{"class":54,"line":131},[52,617,104],{"class":87},[52,619,175],{"class":91},[52,621,178],{"class":58},[52,623,624],{"class":62}," \"Travail en cours",[52,626,200],{"class":58},[52,628,203],{"class":62},[52,630,206],{"class":91},[52,632,633,636],{"class":54,"line":136},[52,634,635],{"class":91},"}",[52,637,639],{"class":638},"sd6ml","   \u002F\u002F affiche « Fermeture » ici\n",[32,641,642],{},"La sortie est : Ouverture, Travail en cours, Fermeture. Le destructeur est appelé même si la fonction se termine par une erreur.",[10,644,646],{"id":645},"raii","RAII",[32,648,649,650,652],{},"Le principe ",[36,651,646],{}," (Resource Acquisition Is Initialization) tient en une phrase : une ressource est acquise dans le constructeur d'un objet et libérée dans son destructeur. Une ressource, c'est de la mémoire, un fichier ouvert, un verrou, une connexion.",[41,654,656],{"className":43,"code":655,"language":46,"meta":47,"style":47},"#include \u003Cfstream>\n\nvoid ecrire() {\n    std::ofstream fichier{\"recettes.txt\"};\n    fichier \u003C\u003C \"Crêpes\\n\";\n}   \u002F\u002F le fichier est fermé automatiquement\n",[49,657,658,665,669,679,696,712],{"__ignoreMap":47},[52,659,660,662],{"class":54,"line":55},[52,661,59],{"class":58},[52,663,664],{"class":62}," \u003Cfstream>\n",[52,666,667],{"class":54,"line":66},[52,668,78],{"emptyLinePlaceholder":77},[52,670,671,674,677],{"class":54,"line":74},[52,672,673],{"class":58},"void",[52,675,676],{"class":142}," ecrire",[52,678,146],{"class":91},[52,680,681,683,685,688,691,694],{"class":54,"line":81},[52,682,104],{"class":87},[52,684,107],{"class":91},[52,686,687],{"class":87},"ofstream",[52,689,690],{"class":91}," fichier{",[52,692,693],{"class":62},"\"recettes.txt\"",[52,695,128],{"class":91},[52,697,698,701,703,706,708,710],{"class":54,"line":95},[52,699,700],{"class":91},"    fichier ",[52,702,178],{"class":58},[52,704,705],{"class":62}," \"Crêpes",[52,707,200],{"class":58},[52,709,203],{"class":62},[52,711,206],{"class":91},[52,713,714,716],{"class":54,"line":101},[52,715,635],{"class":91},[52,717,718],{"class":638},"   \u002F\u002F le fichier est fermé automatiquement\n",[32,720,721,722,725,726,729],{},"Tu n'as pas écrit de ",[49,723,724],{},"close()",". L'objet ",[49,727,728],{},"fichier"," le fait dans son destructeur, quel que soit le chemin de sortie de la fonction.",[731,732,733],"tip",{},[32,734,735,736,739,740,743],{},"C'est la raison pour laquelle on évite ",[49,737,738],{},"new"," et ",[49,741,742],{},"delete"," à la main. Une classe qui libère ses ressources toute seule supprime toute une catégorie de fuites.",[10,745,747],{"id":746},"la-règle-du-zéro","La règle du zéro",[32,749,750,751,161,754,757,758,761],{},"Si ta classe ne contient que des membres qui se gèrent eux-mêmes (",[49,752,753],{},"std::string",[49,755,756],{},"std::vector",", pointeurs intelligents), tu n'écris ni destructeur, ni constructeur de copie : le compilateur génère les bons. C'est la ",[36,759,760],{},"règle du zéro",", à viser par défaut.",[32,763,764,765,768],{},"Tu ne définis ces fonctions que si ta classe gère directement une ressource brute. Dans ce cas, applique aussi la ",[36,766,767],{},"règle des cinq"," : destructeur, constructeur de copie, affectation par copie, constructeur de déplacement et affectation par déplacement vont ensemble.",[10,770,772],{"id":771},"à-retenir","À retenir",[15,774,775,781,786,789,796,799],{},[18,776,777,778,780],{},"Une classe regroupe des données et des méthodes ; on garde les données ",[49,779,232],{},".",[18,782,783,784,780],{},"Une méthode qui ne modifie pas l'objet se marque ",[49,785,263],{},[18,787,788],{},"Le constructeur initialise l'objet, de préférence via la liste d'initialisation.",[18,790,791,792,795],{},"Le destructeur ",[49,793,794],{},"~Classe()"," s'exécute automatiquement à la destruction de l'objet.",[18,797,798],{},"RAII : acquérir la ressource dans le constructeur, la libérer dans le destructeur.",[18,800,801],{},"Vise la règle du zéro : laisse les membres standards gérer leurs ressources.",[803,804,805],"style",{},"html pre.shiki code .sOnC1, html code.shiki .sOnC1{--shiki-light:#CF222E;--shiki-default:#FF7B72;--shiki-dark:#FF7B72}html pre.shiki code .shWOn, html code.shiki .shWOn{--shiki-light:#0A3069;--shiki-default:#A5D6FF;--shiki-dark:#A5D6FF}html pre.shiki code .sIXEE, html code.shiki .sIXEE{--shiki-light:#953800;--shiki-default:#FFA657;--shiki-dark:#FFA657}html pre.shiki code .scfrF, html code.shiki .scfrF{--shiki-light:#1F2328;--shiki-default:#E6EDF3;--shiki-dark:#E6EDF3}html pre.shiki code .syCW7, html code.shiki .syCW7{--shiki-light:#8250DF;--shiki-default:#D2A8FF;--shiki-dark:#D2A8FF}html pre.shiki code .s5iOY, html code.shiki .s5iOY{--shiki-light:#0550AE;--shiki-default:#79C0FF;--shiki-dark:#79C0FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sd6ml, html code.shiki .sd6ml{--shiki-light:#6E7781;--shiki-default:#8B949E;--shiki-dark:#8B949E}",{"title":47,"searchDepth":66,"depth":74,"links":807},[808,809,810,811,812,813,814,815],{"id":12,"depth":66,"text":13},{"id":29,"depth":66,"text":30},{"id":222,"depth":66,"text":223},{"id":365,"depth":66,"text":366},{"id":514,"depth":66,"text":515},{"id":645,"depth":66,"text":646},{"id":746,"depth":66,"text":747},{"id":771,"depth":66,"text":772},"Définir ses propres types avec les classes, initialiser un objet avec un constructeur et libérer ses ressources automatiquement grâce au destructeur (RAII).","md",{},[84,355,372,520,646,232,218,820,477],"méthode const","intermediaire","\u002Fcpp\u002Fclasses-et-raii",[824],"\u002Fcpp\u002Freferences-et-pointeurs",[826,830],{"nom":827,"url":828,"type":829},"OpenClassrooms, Apprenez à programmer en C++","https:\u002F\u002Fopenclassrooms.com\u002Ffr\u002Fcourses\u002F1894236-programmez-avec-le-langage-c","cours",{"nom":831,"url":832,"type":833},"cppreference.com, référence C++ en français","https:\u002F\u002Ffr.cppreference.com\u002Fw\u002Fcpp","doc",{"title":5,"description":816},[836,839],{"nom":837,"url":838},"cppreference.com, classes (en anglais)","https:\u002F\u002Fen.cppreference.com\u002Fw\u002Fcpp\u002Flanguage\u002Fclasses",{"nom":840,"url":841},"C++ Core Guidelines (en anglais)","https:\u002F\u002Fisocpp.github.io\u002FCppCoreGuidelines\u002FCppCoreGuidelines","cpp\u002F05.classes-et-raii","S2cuK6uidq1sXz1rlcbsTU-hmE37OvzsOFbgvQJoKT8",[845,849,853,857,860,861,865],{"path":846,"title":847,"stem":848},"\u002Fcpp\u002Fpremier-programme","Premier programme","cpp\u002F01.premier-programme",{"path":850,"title":851,"stem":852},"\u002Fcpp\u002Fconditions-boucles-fonctions","Conditions, boucles et fonctions","cpp\u002F02.conditions-boucles-fonctions",{"path":854,"title":855,"stem":856},"\u002Fcpp\u002Fstring-et-vector","std::string et std::vector","cpp\u002F03.string-et-vector",{"path":824,"title":858,"stem":859},"Références et pointeurs","cpp\u002F04.references-et-pointeurs",{"path":822,"title":5,"stem":842},{"path":862,"title":863,"stem":864},"\u002Fcpp\u002Fmemoire-et-bibliotheque","Mémoire, pointeurs intelligents et bibliothèque standard","cpp\u002F06.memoire-et-bibliotheque",{"path":866,"title":867,"stem":868},"\u002Fcpp","C++","cpp\u002Findex",[870,872],{"title":858,"path":824,"stem":859,"description":871,"children":-1},"Comprendre les adresses mémoire, passer des arguments sans copie avec les références et manipuler des pointeurs en sécurité.",{"title":863,"path":862,"stem":864,"description":873,"children":-1},"Distinguer pile et tas, gérer la propriété avec unique_ptr et shared_ptr, puis utiliser les algorithmes et std::map de la bibliothèque standard.",[875],{"path":824,"title":858,"ligne":46},[877,879,880,881,882,883,885],{"path":846,"title":847,"niveau":878,"stem":848},"debutant",{"path":850,"title":851,"niveau":878,"stem":852},{"path":854,"title":855,"niveau":878,"stem":856},{"path":824,"title":858,"niveau":821,"stem":859},{"path":822,"title":5,"niveau":821,"stem":842},{"path":862,"title":863,"niveau":884,"stem":864},"avance",{"path":866,"title":867,"niveau":886,"stem":868},"memo",1794583456650]