/* IFT1166 - démonstration #8 - exercice 04 12-novembre -2005 v1.04 M.Lokbani - MàJ pour A05 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) 2003-2005 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, nous avons complété cet exercice par la surdéfinition de l'opérateur d'affectation et nous avons introduit trois fonctions quelconques "void p_val(compte c)" , "void p_ref(compte& c)" et "compte Easy(int x)". */ #include using namespace std; class compte { float solde; int nip; static int nb; public: ~compte () { cout << "D "<< nb << endl; nb--; } // La création d'un objet sans passage d'argument compte () { nb++; cout << "C0 " << nb << endl; } compte (float m, int n) { nb++; solde = m; nip =n; cout << "C1 "<< nb << endl; } compte (const compte& autre){ nb++; solde = autre.solde; nip = autre.nip; cout << "R " << nb << endl; } // L'opérateur d'affectation utilisé dans le main compte & operator = (const compte & v) { cout << "Affectation de (" << v.solde << ',' << v.nip << ")\n"; return (*this); } static void affiche(){ cout << "nb: " << nb << endl; } }; int compte::nb = 0; // trois fcts qqconques void p_val(compte c) { cout << "p_val" << endl; } void p_ref(compte& c) { cout << "p_ref" << endl; } compte Easy(int x) { compte p; cout << "Easy " << x << endl; return p; } 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) // 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; } /* >demo8exo4sol C1 1 C1 2 R 3 R 4 C0 5 Affectation de (200,222) Affectation de (200,222) p_ref R 6 p_val D 6 C0 6 Easy 10 D 6 C1 6 D 6 R 6 D 6 R 6 R 7 R 8 nb: 8 C0 9 C0 10 C0 11 D 11 D 10 D 9 C1 9 C1 10 nb: 10 Affectation de (200,222) D 10 D 9 D 8 D 7 D 6 D 5 D 4 D 3 D 2 D 1 >Exit code: 0 */