Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Ereditarietà in C++
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Specializzazione e inclusione quindi Avremmo potuto definire S’ come: S’ è incluso in S perché la definizione di S’ specializza quella di S
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Specializzazione e algebre Un gruppo G = (S, +, 0, ) è una struttura tale che … Un anello A = (S, +, 0, , ) è una struttura tale che: 1.(S, +, 0, ) sia un gruppo commutativo 2. distribuisca su + Un anello è un gruppo con opportune proprietà cui si aggiunge una nuova operazione (il prodotto).
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Gerarchie di specializzazione Membro-Università Amministrativo Studente-Triennio Studente-Biennio Dottorando Docente OrdinarioAssociatoRicercatore DipendenteStudente
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Gerarchie di specializzazione Figura Figura2D Figura3D Cerchio Triangolo Quadrato Sfera Cubo Tetraedro
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Classi base e classi derivate Se A deriva da B allora A è sottoclasse di B. Il processo di ideazione e realizzazione di un programma può vedersi come definizione di classi per progressivi specializzazione e reffinamento di una a più classi base Classe base: classe utilizzata per definire ulteriori specializzazioni Classe derivata: classe ottenuta per specializzazione di una o più classi Classe base: classe utilizzata per definire ulteriori specializzazioni Classe derivata: classe ottenuta per specializzazione di una o più classi
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Classi base e classi derivate class Point2D { private: double x, y; public: Point2D (double a, double b); void SetX( double a); void SetY( double b); double GetX() const { return x;} double GetY() const { return y;} };
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Classi base e classi derivate class Point3D : public Point2D { private: double z; public: Point3D (double a, double b, double c); void SetZ( double c); double GetZ() const { return z;} }; Classe derivata dalla classe base Point2D Una classe derivata possiede tutti i membri della classe base, cui se ne aggiungono degli altri.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 La relazione “è un”: sottotipo Se Y è derivata di X, allora ogni oggetto di classe Y è un oggetto di classe X Se Y è derivata di X, allora ogni oggetto di classe Y è un oggetto di classe X Point3D p(1.0, 4.5, 0.0); cout << p.GetX(); // stampa 1 cout << p.GetZ(); // stampa 0 Point2D* pt = &p; // p è usato come Point2D pt->SetY(3); cout << p.GetY(); // stampa 3 double x = pt->GetZ(); // errore di tipo!!
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Visibilità class Point2D { private: double x, y; public: } class Point3D : public Point2D { private: double z; public:... double bump() const { return x;} // errore }; x è un campo privato della classe base
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Visibilità class Point2D { protected: double x, y; public: } class Point3D : public Point2D { private: double z; public:... double bump() const { return x;} // ok! }; x è un campo “protected” della classe base I campi “protected” sono visibili alla classe base ed a tutte le sue derivate
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Visibilità Nella derivazione “public”: i membri pubblici sono ovunque visibili; i membri privati sono visibili solo nella classe cui appartengono; i membri protected sono visibili nella classe cui appartengono ed in tutte le sue derivate. Nella derivazione “public”: i membri pubblici sono ovunque visibili; i membri privati sono visibili solo nella classe cui appartengono; i membri protected sono visibili nella classe cui appartengono ed in tutte le sue derivate. La modalità protected viola la regola di incapsulamento
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Overriding class Point2D { public:... void print(); }; void Point2D::print() { cout << x << ',' << y; } class Point3D { public:... void print(); }; void Point3D::print() { cout << GetX() << ',' << GetY() << ',' << z; } La nuova definizione di print() sostituisce la vecchia per i punti 3D
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Overriding void Point3D::print() { Point2D::print(); // chiama la funzione print della classe base cout << ',' << z; } La vecchia definizione di print() può essere usata nella nuova, ma si deve usare la risoluzione dello scope
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Overriding Una classe derivata può ridefinire un metodo (funzione membro) della classe base; la nuova versione deve avere lo stesso nome la stessa segnatura. Overriding: specializzazione dei metodi per gli oggetti di una classe derivata; contrapposto a Overloading: varianti di un metodo in funzione della segnatura.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Costruttori class Point2D { protected: double x, y; public: Point2D (double a, double b) : x(a), y(b) {};... }; Costruttore analogo a: Point2D (double a, double b) { x = a; y = b;}
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Costruttori Point3D (double a, double b, double c) : Point2D(a,b) { z = c;} oppure Point3D (double a, double b, double c) : Point2D(a,b), z(c) {} In ogni caso il costruttore della classe base deve essere usato, e viene eseguito prima di quello della classe derivata
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 La relazione “ha un” template class Stack { private: List s; public: void push(T x) { s.InsertAtFront(x);} void pop (T& x){ s.RemoveFirst(x); } bool IsEmpty() { return s.IsEmpty();} };
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 La relazione “implementa in termini di” template class Stack : private List { public: void push(T x) { InsertAtFront(x);} void pop (T& x){ RemoveFirst(x); } bool IsEmpty() { return IsEmpty();} };
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Visibilità dei campi nelle derivazioni public e private class A { private: int x; protected: int y; public: int z; }; class B : private A { private: int a; protected: int b; public: c; // x non e’ accessibile; y e z lo sono }; class C : public B { public: // non sono accessibili x, y, z, a, // sono accessibili b, c }; ha l’effetto di rendere privati tutti i campi di classe A per gli oggetti di classe C (sottoclasse di B )
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Legami statici e dinamici class Strumentista { public: void chisono (){cout << “un strumentista”; virtual void cosasuono() {cout << “uno strumento”; } } class Violinista: public Strimentista { public: void chisono (){cout << “un violinista”; void cosasuono() {cout << “il violino”; } } Violinista v; Strumentista *ps = &v; ps->chisono(); // stampa “un strumentista” Ps->cosasuono(); // stampa “il violino”
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11 Funzioni virtuali e classi astratte Il C++ ha legame statico, per ottenere gli effetti del legame dinamico i metodi che possono essere ridefiniti nelle sottoclassi devono essere preceduti da virtual class A { private: int x; public: virtual void f(){x = 0};} class B : public A { private: int y; public void f() {y = 1;} A a; B b; A* p = &a; p->f(); // pone a.x = 0 p = &b; p->f(); // pone b.y = 1 Una classe è astratta se contiene almeno un metodo virtuale puro, ossia (essenzialmente) privo di corpo virtual void g() = 0; // funzione virtuale pura è usata solo come classe base e non per produrre oggetti e definisce un’interfaccia.