Costruttori/distruttori. Sovraccarico degli operatori. Ugo de'Liguoro - Informatica 2. Sovraccarico Costruttori/distruttori Quando un oggetto viene allocato viene eseguita una routine di inizializzazione: il costruttore. Quando viene deallocato si esegue un distruttore Ugo de'Liguoro - Informatica 2. Sovraccarico Necessità di un cotruttore Ratio::Ratio(int n, int d) { Assign(n, d); } void Ratio::Assign (int n, int d) { if (d != 0) {num = n, den = d;} else cout << "divisione per 0" << endl; } Il costruttore mantiene l’invariante “il denominatore è sempre ≠ 0” Ugo de'Liguoro - Informatica 2. Sovraccarico 1 Costruttori e oggetti statici class Ratio { costruttore public: Ratio (int n=0, int d=1) { num = n; den = d;} private: ... }; default Ratio a (7, 4); // a vale 7/4 Ratio b (7); // b vale 7/1 Ratio c; // c vale 0/1 Ugo de'Liguoro - Informatica 2. Sovraccarico Oggetti e valori Un oggetto può essere il valore di una funzione o di un metodo Già l’ANSI-C consente di ritornare strutture Ratio Ratio::Sum (Ratio r) { Ratio q (num*r.den+den*r.num,den*r.den); return q; } Ugo de'Liguoro - Informatica 2. Sovraccarico Costruttore di copia class Ratio { Costruttore di copia (= default) public: Ratio (int n=0, int d=1) { num = n; den = d;} Ratio (const Ratio& r) { num = r.num; den = r.den;} private: ... }; Ratio a (2,3); Ratio b(a); // b è un clone di a Ugo de'Liguoro - Informatica 2. Sovraccarico 2 Costruttore di copia Il costruttore di copia viene invocato quando: • si definisce un oggetto in termini di uno già definito: Ratio r Ratio(q); • Nelle assegnazioni o inizializzazioni: Ratio r = q; • si passa una argomento per valore ad una funzione • quando una funzione restituisce un valore Ugo de'Liguoro - Informatica 2. Sovraccarico Costruttore di copia Il costruttore di copia viene invocato quando: • … • si passa una argomento per valore ad una funzione Ratio (const Ratio& r) Il passaggio per riferimento è allora necessario Ugo de'Liguoro - Informatica 2. Sovraccarico Polinomi class Polinomio { public: Polinomio (int degree, double c[]); // Pre: c[] ha dimensione >= degree + 1 // Post: genera il polinomio di grado degree e // coefficienti c[0..degree] (in ordine decr. di grado) Polinomio (const Polinomio& p); // costr. di copia ~Polinomio (); // distruttore private: double* coefficienti; ... Ugo de'Liguoro - Informatica 2. Sovraccarico 3 Polinomi Polinomio q (p); Questo si otterrebbe usando il costruttore di copia di default Ugo de'Liguoro - Informatica 2. Sovraccarico Polinomi Polinomio::Polinomio (const Polinomio& p) { degree = p.degree; coeff = new double[degree + 1]; for (int i = 0; i < degree + 1; i++) coeff[i] = p.coeff[i]; } Polinomio q (p); p q Ugo de'Liguoro - Informatica 2. Sovraccarico Sovraccarico degli operatori Il C++ consente di ridefinire i suoi operatori: Ratio p(2,3), q(1,4); Ratio r = p + q; Questa è una somma di razionali class Ratio { ... public: Ratio operator+ (const Ratio& r); ... } Ratio Ratio::operator+ (const Ratio& r) { } return Ratio(num * r.den + r.num * den, den * r.den); Ugo de'Liguoro - Informatica 2. Sovraccarico 4 Sovraccarico degli operatori class Ratio { ... public: Ratio operator+ (const Ratio& r); ... } Ratio Ratio::operator+ (const Ratio& r) { Funzione membro return Ratio(num * r.den + r.num * den, den * r.den); } Ratio p(1,2), q(2,3); Ratio r = p + q; // equivale a r = p.operator+(q) Ugo de'Liguoro - Informatica 2. Sovraccarico Sovraccarico degli operatori class Ratio { ... public: Ratio operator+ (const Ratio& r); ... } Ratio Ratio::operator+ (const int n) { return Ratio(num * n, den); } Ratio p(1,2); int n = 3; Ratio r = p + n; // equivale a r = p.operator+(n) Ratio r = n + p; // ERRORE: n.operator+(q) non è definito Ugo de'Liguoro - Informatica 2. Sovraccarico Sovraccarico degli operatori class Ratio { ... public: Ratio operator+ (const Ratio& r); ... } friend Ratio Ratio::operator+ (const int n, const Ratio& r)) { return Ratio(num * n, den); } Funzione friend Ratio p(1,2); int n = 3; Ratio r = n + p; // OK Se il primo parametro non appartiene alla classe la funzione non può essere membro Ugo de'Liguoro - Informatica 2. Sovraccarico 5 Sovraccarico degli operatori friend ostream& operator<< (ostream& os, const Ratio& r); … ostream& operator<< (ostream& os, const Ratio& r) { if (r.den != 1) os << r.num << '/' << r.den; else os << r.num; return os; Tipico esempio: la ridefinizione dell’ I/O cout << r; // r è di classe Ratio Ugo de'Liguoro - Informatica 2. Sovraccarico Sovraccarico di = Polinomio& Polinomio::operator= (const Polinomio& p) { if (&p != this) if { // non esegue se c'è autorif. (degree != p.degree) { // la dimensione di coeff è diversa delete [] coeff; // libera la memoria occupata dal vecchio degree = p.degree; coeff = new Ratio[degree + 1]; } for (int i = 0; i < degree + 1; i++) // copia dei coefficienti coeff[i] = p.coeff[i]; } return *this; } // consente assegnazioni come p = q = f; Ugo de'Liguoro - Informatica 2. Sovraccarico 6