220 likes | 383 Views
Ereditarietà in C++. Specializzazione e inclusione. quindi. S’ è incluso in S perché la definizione di S’ specializza quella di S. Avremmo potuto definire S’ come:. Specializzazione e algebre. Un gruppo G = (S, +, 0, ) è una struttura tale che …
E N D
Ereditarietà in C++ Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11
Specializzazione e inclusione quindi S’ è incluso in S perché la definizione di S’ specializza quella di S Avremmo potuto definire S’ come: 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: • (S, +, 0, ) sia un gruppo commutativo • 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 Dipendente Studente Studente-Triennio Dottorando Amministrativo Docente Studente-Biennio Ordinario Associato Ricercatore Membro-Università Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11
Gerarchie di specializzazione Figura3D Figura2D Sfera Cerchio Quadrato Cubo Tetraedro Triangolo Figura 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 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 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! }; Icampi “protected” sono visibili alla classe base ed a tutte le sue derivate x è un campo “protected” della classe base 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. 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(); }; La nuova definizione di print() sostituisce la vecchia per i punti 3D void Point3D::print() { cout << GetX() << ',' << GetY() << ',' << z; } 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 T> class Stack { private: List<T> 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 T> class Stack : private List<T> { 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 . Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 11