/* IFT1169 - démonstration #03 - exercice 04 30-janvier -2006 v1.04 M.Lokbani - màj pour IFT1169 + gcc3.4.2 exemple pris de H. Garreta 31-octobre -2003 v1.03 M.Lokbani - De démo06exo3 MàJ pour démo07exo2 22-octobre -2003 v1.02 M.Lokbani - gcc3.2 +comments. 15-octobre -1999 v1.01 P.Langlais - +comments 05-octobre -1999 v1.00 M.Lokbani - énoncé + corrigé. contact: lokbani@iro.umontreal.ca Copyright (C) 1999-2006 Université de Montréal Département d'informatique et de Recherche Opérationnelle Mohamed Lokbani -- Tous Droits Réservés -- All Rights Reserved -- Description: ------------ Le but de cet exercice est l'utilisation du constructeur, destructeur et constructeur de recopie. Les points saillants: 1) new appelle tjs un constructeur (après la création de l'objet) 2) delete, tjs le destructeur (avant la destruction de l'objet) 3) constructeur par recopie dans des situations comme a) passage d'un argument par valeur, b) retour par valeur d'un objet par une fonction c) initialisation d'un objet avec un autre objet du même type, ssi au moment de la déclaration => Cas d'initialisation par un autre objet (!= affectation) 4) il existe un constructeur par défaut => recopie partielle Par rapport à l'exercice 3 de la démonstration #6, nous avons complété cet exercice par la surdéfinition de l'opérateur d'affectation et nous avons introduit l'utilisation des fonctions amies. */ #include using namespace std; class compte { float solde; int nip; static int nb; public: // La destruction d'un objet ~compte () { cout << "D "<< nb << endl; nb--; } // La création d'un objet sans passage d'argument compte () { nb++; cout << "C0 " << nb << endl; } // La création d'un objet avec passage de deux arguments compte (float m, int n) { nb++; solde = m; nip =n; cout << "C1 "<< nb << endl; } // Opérateur de recopie : il est conseille de mettre le const // => ça marchera aussi bien pour les objets constants que les autres. // la référence est ici imposée par C++, car sinon on aurait appel a // l'opérateur de recopie => boucle infinie (allez prendre un café) compte (const compte& autre){ nb++; solde = autre.solde; nip = autre.nip; cout << "R " << nb << " de (" << autre.solde << ',' << autre.nip << ")\n"; } // L'opérateur d'affectation utilisé dans le main compte & operator = (const compte & v) { cout << "Affectation de (" << v.solde << ',' << v.nip << ")\n"; return (*this); } void affiche(){ cout << "solde: " << solde << endl; } // L'utilisation de fonctions amies friend compte AddCompte(const compte, int); friend compte Easy(int); }; // Partie définition (.cc ou .cpp) int compte::nb = 0; // init d'un membre static // fct friend compte AddCompte(const compte c, int somme) { compte p = c; p.solde += somme; return p; } compte Easy(int x) { compte p; cout << "Easy " << x << endl; return p; } // deux fcts qqconques void p_val(compte c) { cout << "p_val" << endl;} void p_ref(compte& c) { cout << "p_ref" << endl;} int main() { compte c1(100, 111); // C1 compte c2(200, 222); // C1 // En fait la même syntaxe // Il s'agit de l'initialisation lors de la déclaration // => constructeur de recopie (par défaut ou effectif, s'il existe) compte c3 = c2; // R (de c2) compte c4(c1); // R (de c1) // !!! uniqt si un constructeur sans argument existe // ou qu'aucun constructeur n'est donné compte c5; c3 = c2; // pas de création, pas de recopie !!! => op. Affectation c5 = c2; // pas de création, pas de recopie !!! => op. Affectation p_ref(c1); // rien au niveau des constructeurs p_val(c1); // recopie puis destruction (objet automatique) => R puis D (de l'objet local à la fct) Easy(10); // D (de l'objet alloué pour le retour) AddCompte(c1,1000); // R (de c1) R (ligne 1 de la fct), R (du résultat), puis D D D ouatch !!! compte p = AddCompte(c1,1000); // R (de c1) R (ligne 1 de la fct), R (du résultat), puis D D ouatch !!! // Un D de moins car un objet est bien crée (ici p) compte* pc = new compte(800, 333); // C1 delete pc; // D 5 compte* pc2 = new compte(c1); // R (recopie car c1 existe déjà) delete pc2; // D compte banque[3] = {c1, c2, c3}; // R R R : création de 3 objets par recopie banque[0].affiche(); compte *table; table = new compte [3]; // !!!! Erreur si pas de constructeur sans argument sinon C0 C0 C0 delete [] table; // D D D compte table2[2] = {compte(1,2),compte(2,3)}; // C1 C1 table2[0].affiche(); // affectation c1 = c2; // Et puis tous les deletes (D) dans n'importe quel ordre. return 0; } /* >1169demo03exo4Sol C1 1 C1 2 R 3 de (200,222) R 4 de (100,111) C0 5 Affectation de (200,222) Affectation de (200,222) p_ref R 6 de (100,111) p_val D 6 C0 6 Easy 10 D 6 R 6 de (100,111) R 7 de (100,111) D 7 D 6 R 6 de (100,111) R 7 de (100,111) D 7 C1 7 D 7 R 7 de (100,111) D 7 R 7 de (100,111) R 8 de (200,222) R 9 de (200,222) solde: 100 C0 10 C0 11 C0 12 D 12 D 11 D 10 C1 10 C1 11 solde: 1 Affectation de (200,222) D 11 D 10 D 9 D 8 D 7 D 6 D 5 D 4 D 3 D 2 D 1 >Exit code: 0 */