Title: Nessun titolo diapositiva
1FONDAMENTI DI INFORMATICA IIIngegneria
Gestionalea.a. 2001-2002 - 4
CicloOverloading degli Operatori
2Overloading degli Operatori
- Definizione
- Loverloading degli operatori serve a definire,
per mezzo degli operatori tradizionali, le
operazioni che coinvolgono i dati dei tipi nuovi
definiti dallutente. Gli operatori utilizzabili
sono cioè quelli già definiti come tali nel C e
la ridefinizione delle operazioni che essi
potranno eseguire non influirà sulla loro - precedenza,
- associatività,
- e numero di operandi.
- Metodo per loverloading
- Loverloading di un operatore si ottiene
definendo una funzione con il nome composto dalla
parola riservata operator seguita dalloperatore
da ridefinire (ad es. operator, operator,
..ecc.)
3Overloading degli Operatori
- Ridefinibilità degli operatori
- Tutti gli operatori possono essere ridefiniti,
tranne i seguenti - . . ? sizeof
- Tipologia delle funzioni di overloading degli
operatori - Le funzioni di overloading degli operatori
- devono essere funzioni membro di una classe per
tutti gli operatori di assegnazione e per gli
operatori - ( ) -gt
- devono essere funzioni non membro (da dichiarare
se possibile friend, per migliorarne
lefficienza) quando si ridefiniscono con cout e
cin gli operatori - ltlt gtgt
- possono essere sia funzioni membro che non
membro (da dichiarare se possibile friend, per
migliorarne lefficienza) per tutti gli altri
operatori.
4Overloading degli Operatori
- Nota
- E bene tener presente che nel caso di funzione
di overloading di operatore, definita come
funzione membro, essa non può essere dichiarata
static. - Operatività delloverloading degli operatori
- Un operatore ridefinito per gli oggetti di una
determinata classe viene richiamato quando - nel caso di operatore binario, loperando
sinistro è un oggetto della classe, oppure - nel caso di operatore unario, lunico operando è
un oggetto della classe.
5Overloading degli Operatori
Overloading di operatori binari con funzioni
membro La funzione di ridefinizione
delloperatore assume la forma Prototipo Tipo_Re
stituito operator Segno_Operatore
(Tipo_Argomento) Implementazione Tipo_Restituito
operator Segno_Operatore (Tipo_Argomento
Variabile_Argomento) codice della
funzione... La suddetta implementazione viene
invocata quando in una espressione . Variabile1
Segno_Operatore Variabile2 . la
Variabile1 (almeno) è un oggetto della classe e,
in tal caso, linvocazione assume la forma
Variabile1. operator Segno_Operatore
(Variabile2)..
6Overloading degli Operatori
Overloading di operatori binari con funzioni
membro Nellambito del codice della funzione
membro di nome operatorSegno_Operatore si ha
laccesso immediato a tutti i dati membro
pubblici e privati relativi alloggetto
Variabile1 (che è loggetto per cui viene
invocata la funzione), mentre gli stessi dati
sono accedibili per loggetto Variabile2
selezionandoli con il nome delloggetto stesso
(ossia con Variabile2 . Nome_dato) Mediante i
suddetti accessi ai dati membro degli oggetti
Variabile1 e Variabile2 è possibile ridefinire il
Segno_Operatore facendogli fare una operazione
diversa da quella originale, e restituendo, poi,
una variabile del tipo indicato nel prototipo.
7Overloading degli Operatori
Esempio di overloading di operatori binari con
funzioni membro include ltiostream.hgt class
Cmplex public Cmplex (int, int) Cmplex
operator (Cmplex) Cmplex operator
(Cmplex) int r,i CmplexCmplex (int rea,
int ima) r rea i ima
8Overloading degli Operatori
Cmplex Cmplexoperator (Cmplex c2) Cmplex
csum (0, 0) csum.r r c2.r csum.i i
c2.i return csum Cmplex Cmplexoperator
(Cmplex d) return Cmplex (d.r, d.i) int
main() Cmplex a(5, 5) Cmplex b(2, 2) Cmplex
c(0, 0) c ab coutltltc.rltlt"i"ltltc.iltltendl re
turn 0
9Overloading degli Operatori
Overloading di operatori binari con funzioni non
membro La funzione di ridefinizione
delloperatore assume la forma Prototipo Tipo_Re
stituito operator Segno_Operatore
(Tipo_Argomento, Tipo_Argomento) Implementazione
Tipo_Restituito operator Segno_Operatore
(Tipo_Argomento1 Variabile_Argomento1,
Tipo_Argomento2 Variabile_Argomento2 )
codice della funzione... La suddetta
implementazione viene invocata quando in una
espressione . Variabile1 Segno_Operatore
Variabile2 . la Variabile1 (almeno) è un
oggetto della classe e, in tal caso,
linvocazione assume la forma operator
Segno_Operatore (Variabile1, Variabile2)..
10Overloading degli Operatori
Overloading di operatori binari con funzioni non
membro Nellambito del codice della funzione non
membro di nome operatorSegno_Operatore si ha
laccesso a tutti i dati membro pubblici (e anche
privati, se la funzione è stata definita friend)
relativi agli oggetti Variabile1 e Variabile2,
selezionandoli con il nome degli oggetti stessi
(ossia con Variabile1 . Nome_dato, Variabile2 .
Nome_dato). Mediante i suddetti accessi ai dati
membro degli oggetti Variabile1 e Variabile2 è
possibile ridefinire il Segno_Operatore
facendogli fare una operazione diversa da quella
originale, e restituendo, poi, una variabile del
tipo indicato nel prototipo.
11Overloading degli Operatori
Esempio di overloading di operatori binari con
funzioni non membro include ltiostream.hgt class
Complesso friend Complesso operator
(Complesso, Complesso) public Complesso
(int0, int0) Complesso operator
(Complesso) int getReal ( ) return r int
getImagin ( ) return i private int
r,i ComplessoComplesso (int a, int
b) r a i b
12Overloading degli Operatori
Complesso operator (Complesso ca, Complesso
cb) int re ca.r cb.r int im ca.i
cb.i return Complesso (re, im) Complesso
Complessooperator (Complesso cm) return
Complesso (cm.r, cm.i) int main (
) Complesso c1(4, 5) Complesso c2(6,
7) Complesso c3 c1 c2 cout ltlt
c3.getReal( ) ltlt "i" ltlt c3.getImagin ( )
ltlt"\n" return 0
13Overloading degli Operatori
Overloading di operatori unari con funzioni
membro La funzione di ridefinizione
delloperatore assume la forma Prototipo Tipo_Re
stituito operatorSegno_Operatore (
) Implementazione Tipo_Restituito
operatorSegno_Operatore ( ) codice della
funzione... La suddetta implementazione viene
invocata quando in una espressione .
Segno_Operatore Variabile . la Variabile è
un oggetto della classe e, in tal caso,
linvocazione assume la forma Variabile .
operatorSegno_Operatore ( )..
14Overloading degli Operatori
Overloading di operatori unari con funzioni
membro Nellambito del codice della funzione
membro di nome operatorSegno_Operatore si ha
laccesso immediato a tutti i dati membro
pubblici e privati relativi alloggetto
Variabile (che è loggetto per cui viene invocata
la funzione). Mediante i suddetti accessi ai dati
membro delloggetto Variabile è possibile
ridefinire il Segno_Operatore facendogli fare una
operazione diversa da quella originale, e
restituendo, poi, una variabile del tipo indicato
nel prototipo.
15Overloading degli Operatori
Esempio di overloading di operatori unari con
funzioni membro include ltiostream.hgt class
Angle public Angle (int0) Angle operator (
) int get( ) private int arc AngleAngle
(int a) arc a
16Overloading degli Operatori
Angle Angleoperator ( ) arc -360 (arc
360) return Angle(arc) int Angleget(
) return arc int main ( ) Angle
arco(50) arco arco cout ltlt arco.get(
) return 0
17Overloading degli Operatori
Overloading di operatori unari con funzioni non
membro La funzione di ridefinizione
delloperatore assume la forma Prototipo Tipo_Re
stituito operatorSegno_Operatore
(Tipo_Argomento) Implementazione Tipo_Restituito
operatorSegno_Operatore (Tipo_Argomento
Variabile_Argomento) codice della
funzione... La suddetta implementazione viene
invocata quando in una espressione .
Segno_Operatore Variabile . la Variabile è
un oggetto della classe e, in tal caso,
linvocazione assume la forma operator
Segno_Operatore (Variabile)..
18Overloading degli Operatori
Overloading di operatori unari con funzioni non
membro Nellambito del codice della funzione non
membro di nome operatorSegno_Operatore si ha
laccesso a tutti i dati membro pubblici (e anche
privati, se la funzione è stata definita friend)
relativi alloggetto Variabile, selezionandoli
con il nome delloggetto stesso (ossia con
Variabile . Nome_dato). Mediante i suddetti
accessi ai dati membro delloggetto Variabile è
possibile ridefinire il Segno_Operatore
facendogli fare una operazione diversa da quella
originale, e restituendo, poi, una variabile del
tipo indicato nel prototipo.
19Overloading degli Operatori
Esempio di overloading di operatori unari con
funzioni non membro include ltiostream.hgt class
Angle public Angle (int 0) int get (
) private int arc AngleAngle (int
a) arc a int Angleget ( ) return arc
20Overloading degli Operatori
Angle operator (Angle val) int compl -360
(val.get( ) 360) return Angle
(compl) int main ( ) Angle arco
(60) arco arco cout ltlt arco.get( ) return
0
21Overloading degli Operatori
Conversione tra tipi diversi Nel caso dei tipi
predefiniti la conversione di una variabile di un
tipo ad una di tipo diverso si ottiene
esplicitamente con loperatore static_cast, nel
modo seguente .. static_cast ltTipoBgt
(Variabile_TipoA) . questa espressione crea un
oggetto temporaneo del TipoB a partire dalla
Variabile_TipoA. Nel caso di tipi definiti
dallutente, la stessa cosa, ossia la conversione
da un tipo definito dallutente ad un tipo
primitivo, o viceversa, oppure ad un tipo ancora
definito dallutente, può ottenersi con i
costruttori di conversione, che ricevono un solo
argomento e che convertono gli oggetti di altri
tipi (inclusi i tipi predefiniti) in oggetti di
una determinata classe.
22Overloading degli Operatori
Conversione tra tipi diversi con loperatore di
conversione La conversione nel caso di tipi
definiti dallutente può anche ottenersi per
mezzo di un opportuno operatore di conversione (o
di cast), da costruire con una funzione membro
non static, che deve essere realizzata e
richiamata come indicato nel seguito. L
operatore di conversione viene anche esso
definito per mezzo della parola riservata
operator che, questa volta, non viene utilizzata
in connessione con un operatore da ridefinire, ma
con un tipo (o oggetto) verso il quale si vuole
definire una conversione.
23Overloading degli Operatori
Conversione tra tipi diversi con loperatore di
conversione Prototipo operator TipoB (
) Nota non serve indicare che la funzione
restituisce un oggetto di TipoB perché ciò è
implicito nel fatto che la funzione, come sopra
definita, converte un altro oggetto in un oggetto
di TipoB Implementazione Nome_Classe operator
TipoB ( ) .implementazione della
conversione...return Dato_TipoB Nota il
codice di implementazione della conversione opera
sui dati membro pubblici e privati relativi
alloggetto per il quale la funzione operator
TipoB viene invocata. Invocazione (TipoB)
Oggetto_TipoA che il compilatore traduce in
...Oggetto_TipoA.operator TipoB ( ).
24Overloading degli Operatori
Esempio di conversione tra tipi
diversi includeltiostream.hgt class Complesso
public Complesso (int, int) operator int (
) private int r, i ComplessoComplesso
(int a, int b) r a i b Complessoope
rator int ( ) return (ii rr)
25Overloading degli Operatori
int main ( ) Complesso c(2, 3) int k
(int) c coutltltkltlt"\n" //Presenta
13. return 0
26Overloading degli Operatori
Loverloading degli operatori e - - Gli
operatori e - - operano come operatori di
preincremento e predecremento nel caso che essi
precedano la variable a cui si applicano. In
questo caso il loro overloading non differisce da
quello tradizionale degli operatori unari. Nel
caso che essi seguano la variabile a cui si
applicano essi invece operano come post
incremento e post decremento e, quindi, la loro
operatività va distinta da quella precedente. In
questo secondo caso la distinzione si attua come
indicato nelle pagine che seguono.
27Overloading degli Operatori
Nel caso di post incremento (ma lo stesso vale
per il post decremento), se loverloading è
implementato come funzione membro, quando
sincontra lespressione Variabile il
compilatore genera linvocazione a
funzione Variabile . operator (0) il cui
prototipo sarà Tipo_Restituito operator
(int) dove lo 0 è soltanto un valore fittizio
necessario per distinguere il post incremento dal
preincremento.
28Overloading degli Operatori
Nel caso di post incremento (ma lo stesso vale
per il post decremento), se loverloading è
implementato come funzione non membro, quando
sincontra lespressione Variabile il
compilatore genera linvocazione a funzione
operator (Variabile, 0) il cui prototipo
sarà Tipo_Restituito operator
(Tipo_Variabile, int) dove, anche in questo
caso, lo 0 è soltanto un valore fittizio
necessario per distinguere il post incremento dal
preincremento.