• Non ci sono risultati.

Ingegneria Elettronica Ingegneria delle Telecomunicazioni (J-Z) Ing. Antonio Monteleone A.A. 2001/02 3 ciclo

N/A
N/A
Protected

Academic year: 2022

Condividi "Ingegneria Elettronica Ingegneria delle Telecomunicazioni (J-Z) Ing. Antonio Monteleone A.A. 2001/02 3 ciclo"

Copied!
17
0
0

Testo completo

(1)

Ingegneria Elettronica

Ingegneria delle Telecomunicazioni (J-Z)

Ing. Antonio Monteleone

A.A. 2001/02 – 3° ciclo

(2)

• L’ereditarietà permette di definire una nuova classe a partire da classi già definite.

La nuova classe, detta classe derivata , eredita le funzionalità da una o più classi base da cui deriva ma introduce delle nuove funzionalità che la caratterizzano e la distinguono dalle sue classi base.

• L’ereditarietà può essere singola o multipla

class Derivata : public|protected|private Base { // dichiarazioni...

};

tipo di ereditarietà

(3)

• a

#include “point.h”

class Polygon {

int m_vertexCount;

Point *m_vertexList;

public:

Polygon(int vertexCount, const Point *vertexList);

Polygon(const Polygon & p);

~ Polygon();

void translate(double lx, double ly);

void rotate(const Point &center, double angle);

double perimeter();

};

#include “polygon.h”

class Rectangle : public Polygon { double m_side1, m_side2;

public:

Rectangle(const Point &c, double s1, double s2, double angle);

~ Rectangle();

double diagonal();

(4)

Ereditarietà: lo specificatore d’accesso protected

• I membri protected di una classe sono accessibili soltanto dalle funzioni membro o friend di tale

classe e delle sue classi derivate

class Base { int i;

protected:

int k;

int read() const {return i;}

void set(int ii) { i = ii;

}

public:

Base(int ii = 0) : i(ii), k(0) {}

int value(int m) const { return m*i;

} };

class Derived : public Base { int j;

public:

Derived(int jj = 0) : j(jj) {}

void change(int x) {

k = x*x; // OK:k è protected set(x);

}

}; int main() { Base b;

b.set(20); //non compila Derived d;

d.change(10);

return 0;

}

(5)

Ereditarietà public, protected e private

• Una classe base può essere ereditata come

– class Derived : public Base { /* … */};

I membri public della classe base diventano membri public della classe derivata.

I membri protected della classe base diventano membri protected della classe derivata

– class Derived : protected Base { /* … */};

I membri public e protected della classe base diventano membri protected della classe derivata – class Derived : private Base { /* … */};

I membri public e protected della classe base

diventano membri private della classe derivata

(6)

Ereditarietà public, protected e private (2)

• Il tipo di ereditarietà di default è quello private

• L’ereditarietà di tipo private permette di

implementare una classe “in termini” della sua classe base

class Derived : Base { // dichiarazioni...

};

L’ereditarietà è di tipo private

(7)

Ereditarietà public, protected e private (3)

• L’ereditarietà di tipo public permette di esprimere relazioni is_a tra oggetti

• Nella ereditarietà di tipo public un oggetto di classe derivata può essere usato ovunque può essere usato un oggetto di classe base

class D: public B { // dichiarazioni...

};

Ogni oggetto di tipo D è anche un oggetto di tipo B, ma non viceversa

void f(const B &b) { /*... */ } void g(const D &d) { /*... */ }

void main() { D d;

B b;

f(d); // OK: d è anche un B g(b); // ERR: b non è un D };

(8)

Costruttori di classi derivate (1)

• Un oggetto di una classe derivata contiene un sotto-oggetto appartenente alla sua classe base

• Quando si istanzia un oggetto di una classe derivata viene chiamato prima l’opportuno

costruttore della classe base e poi l’opportuno

costruttore della classe derivata

(9)

Costruttori di classi derivate (2)

• Quando si crea un oggetto di una classe derivata le variabili membro della classe base sono inizializzate mediante l’invocazione di un costruttore di tale

classe nella lista di inizializzatori

class Person { char *m_name;

public:

Person(char *name);

// altre dichiarazioni … char *name();

};

class Employ : public Person { float m_salary;

public:

Employ(char *name, float salary);

// altre dichiarazioni … float salary();

};

Employ::Employ(char *name, float salary) : Person(name)

, m_salary(salary) {}

Chiamata esplicita al costruttore della classe base

(10)

Costruttori di classi derivate (3)

• Se nella costruzione di un oggetto di una classe derivata si omette la chiamata di un costruttore della classe base, il compilatore provvederà a chiamare il costruttore di default di tale classe

class Base { int i;

public:

Base(int ii = 0): i(ii){}

// altre dichiarazioni … };

class Derived : public Base { int j;

public:

Derived(int jj = 0);

// altre dichiarazioni … };

Derived::Derived(int jj) : j(jj) {}

Chiamata implicita al costruttore di default della classe base

(11)

Distruttori di classi derivate

• Quando viene distrutto un oggetto di una classe derivata il distruttore di tale classe viene invocato prima del distruttore di ogni sua classe base

• Il distruttore di una classe base viene chiamato automaticamente, ossia non bisogna invocarlo esplicitamente dal distruttore della classe derivata

class Base { public:

// altre dichiarazioni …

~Base();

}; int main() {

Derived derived;

// …

return 0;

class Derived : public Base { char *a;

public:

// altre dichiarazioni …

~Derived() {

if (a) delete a;

} };

(12)

La ridefinizione di funzioni membro

• In una classe derivata è possibile ridefinire una funzione membro di una sua classe base

• Per invocare la funzione membro della classe base si utilizza l’operatore ::

class Base { public:

// altre dichiarazioni … void f(int a) {

cout << “Base::f” << endl;

// … }

}; int main() {

Derived derived;

derived.f(1);

derived.Base::f(2);

return 0;

}

class Derived : public Base { public:

// altre dichiarazioni … void f(int a) {

cout << “Derived::f” << endl;

// … }

};

(13)

• In C++ è possibile far derivare una classe da più classi base

class Base1 { int ii;

public:

Base1(int i = 0) : ii(i) {}

int value() const { return ii;

} };

class Base2 { char cc;

public:

Base2(char c = 0) : cc(c) {}

char value() const { return cc;

}

class Derived : public Base1 , public Base2 { float jj;

public:

Derived(int i, char c, float j) : Base1(i), Base2(c), jj(j) {}

float getValue() { return jj

}

}; void main() {

Derived d(1,’a’,2.5);

cout << d.Base1::value();

cout << d.Base2::value();

Base1 *pb1 = &d;

cout << pb1->value();

}

(14)

Conversioni tra classi base e derivata (1)

• Nell’ereditarietà di tipo public un oggetto di

classe derivata è anche un oggetto di classe base

• In generale non è possibile assegnare un oggetto di classe base a un oggetto di classe derivata

Employ emp(“Rossi”, 1000);

Person p(“Bianchi”);

p = emp;

la classe derivata contiene tutti i membri della classe base

Employ emp(“Rossi”, 1000);

Person p(“Bianchi”);

emp = p; //errore di compilazione

la classe derivata contiene dei membri non appartenenti alla classe base

(15)

Conversioni tra classi base e derivata (2)

• Nell’ereditarietà di tipo public un puntatore (un riferimento) a un oggetto di classe derivata può essere convertito implicitamente in un puntatore (un riferimento) a un oggetto di classe base (up- cast)

Employ emp(“Rossi”, 1000);

Person *p = &emp;

cout << p->name();

cout << p->salary(); //errore

L’accesso a un oggetto di classe derivata attraverso un puntatore a una sua

classe base è limitato

solo ai membri pubblici di tale classe

void f(const Person &p) { /*... */ } void main() {

Employ emp(“Rossi”, 1000);

f(emp); // up-cast implicito

(16)

Conversioni tra classi base e derivata (3)

• Un puntatore (un riferimento) a un oggetto di classe base può essere convertito solo

esplicitamente in un puntatore (un riferimento) a un oggetto di classe derivata (down-cast)

• Un down-cast va effettuato solo se l’oggetto puntato dal puntatore di classe base è

effettivamente un oggetto di classe derivata

Person p(“Rossi”);

Employ *e1 = &p; //errore di compilazione Employ *e2 = static_cast< Employ *>(&p);

cout << e2->name();

cout << e2->salary(); //errore logico

(17)

class Base {

// dichiarazioni … };

class Derived : public Base { // altre dichiarazioni …

void fun() ; // non e’ definita in Base };

void g(Base *ptr) {

ptr->fun(); // Errore di compilazione

Derived *p = dynamic_cast<Derived *> (ptr);

if (p!=0) p->fun();

}

dynamic_cast

• Il dynamic_cast opera una conversione, se è possibile, fra due tipi. Il puntatore ritornato non è

nullo soltanto se il tipo dell’oggetto su cui si opera è quello che ci si aspetta

void main() {

Base *b1 = new Base();

g(b1); // fun() non è chiamata Base *b2 = new Derived();

g(b2); // fun() è chiamata }

Riferimenti

Documenti correlati

Per ridurre l’esposizione a nanoparticelle, i lavoratori dovrebbero imparare la corretta manipolazione delle nanoparticelle, l’utilizzo dei dispositivi di protezione personale,

1) violazione e falsa applicazione dei principi di imparzialità, trasparenza e par condicio competitorum; violazione del principio di concorrenza; eccesso di potere per

3 Sulla normativa in questione si sono succeduti vari orientamenti a partire da quello fornito dal Dipartimento della funzione pubblica con la circolare n. 1/2013.,

Prova a completare il percorso ricordando che ogni numero è maggiore di uno rispetto al suo precedente:. Ecco formato il numero cento

Per fortuna l’informatore decide di aiutare ancora l’ispettore fornendogli indizi proprio attraverso il computer. Il numero

Finalmente arrivano informazioni sul complice della Signora Violet, l’abilissima ladra arrestata da Numerik.. Gli indizi sono contenuti in una busta chiusa: l’ispettore Numerik la

1) Discutere la legge di Ampere-Maxwell in forma microscopica. 2) Calcolare l’induttanza di due induttori collegati in serie. 3) Formulare la legge di conservazione della

Supponiamo di essere arrivati a un certo passo della costruzione e di saper costruire tutti i punti del piano che hanno coordinate appartenenti a un certo campo di numeri F..