Funzioni in C++ - ICAR-CNR
Download
Report
Transcript Funzioni in C++ - ICAR-CNR
Funzioni
• In C++ le funzioni sono caratterizzate da un nome,
dal tipo della variabile ritornata e da una lista di
parametri (opzionali)
Tipo ritornato
Corpo della
funzione
Parametri
double max( double a, double b)
{
return (a>b) ? a : b;
}
Valore di ritorno
• La lista dei parametri (anche se vuota) deve
essere esplicitata
• Il valore ritornato deve essere compatibile, a meno
di conversione esplicita, con il tipo della funzione
1
Funzioni (2)
Tipo di dichiarazione
C++
commenti
funzione
double cube(double x)
{ return x*x*x; }
parametri passati
“by value”
procedura
void scrivi_quadrato(int i)
{ cout<<i*i<<endl; }
subroutine, non si
usa return
senza argomenti
void hello ()
{ cout<<“Hello”<<endl; }
puo` anche essere
void hello(void)
argomenti passati
per riferimento
void swap(int& i,int& j)
{ int t=i; i=j; j=t; }
i e j hanno i loro
valori scambiati
variabile
int scanf(const char,
inline
inline double cube(int x)
codice inline
argomenti di
default
int power(int i, int n=2)
il 2do argomento
puo` essere
tralasciato
…)
chiamata con un
qualsiasi numero
di argomenti
2
Prototipi delle funzioni
• Prima di essere usata, una funzione deve essere
dichiarata (nel file che la usa)
main.cc
max.cc
#include <iostream>
double max (double a, double b)
double max(double, double);
{
int main()
return (a>b) ? a : b;
{
}
double m = max(1, 3);
cout<<“Il massimo e` “<<m<<endl;
Prototipo di max
return 0;
}
(normalmente in max.h)
• I prototipi rendono le funzioni in C++ “type safe”,
nel senso che i valori reali degli argomenti
vengono all’occorrenza convertiti nei tipi formali
specificati dal prototipo
3
Chiamata per valore
• Con il passaggioper valore la funzione non può
modificare il valore dei suoi argomenti
bool greater(int i, int j) { // se i>j scambia i e j
if (i>j) {
int temp=i;
Argomenti passati “per valore”
i=j;
sono scambiati nella funzione ma
j=temp;
nel programma chiamante hanno
return true;
i valori vecchi
}
else
return false;
}
– Es: int i = 5, j=7;
– Dopo la chiamata di greater (i,j)
– i vale sempre 5 e j vale sempre 7
4
Puntatori come parametri
• L’uso dei puntatori permette ad una funzione di
modificare il valore dei suoi argomenti
bool greater(int *p1, int *p2) { /* se il valore
puntato da p1 > valore puntato da p2 scambia i due
valori*/
if (*p1>*p2) {
int temp=*p1;
Se passo i puntatori le modifiche
*p1=*p2;
Hanno effetto sul programma
*p2=temp;
chiamante
return true;
}
else
return false;
}
– Es: int i = 5, j=7;
– Dopo la chiamata di greater (&i,&j)
– i varrà 7 e j 5
5
Chiamata per riferimento
• L’uso dei riferimenti permette ad una funzione di
modificare il valore dei suoi argomenti
bool greater(int& i, int& j) { // se i>j scambia i e j
if (i>j) {
int temp=i;
Argomenti passati “by reference”
i=j;
possono essere modificati dalla
j=temp;
funzione stessa
return true;
}
else
return false;
}
– Con i riferimenti è sufficiente chiamare greater (i, j);
– Per ragioni di efficenza, oggetti di grandi dimensioni (in
termini di memoria) vengono normalmente passati “by
reference”.
– Per evitare che possano essere modificati dalla
funzione, il riferimento viene definito const
6
Funzioni inline
• La keyword inline suggerisce al compilatore
che ogni chiamata alla funzione deve essere
convertita in codice eseguibile (la definizione
della funzione viene sostituita alla chiamata
dovunque nell codice)
• Le funzioni inline vengono usate per ragioni di
efficienza e (per non sovraccaricare il
compilatore) devono essere semplici
• Il compilatore può decidere autonomamente (per
esempio se la funzione è troppo lunga) di
ignorare la direttiva inline
7
Argomenti di default
• Ad ogni parametro di una funzione può essere
assegnato un valore di default. Questo permette di
chiamare la funzione tralasciando quei parametri il
cui valore di default risulta appropriato
main.cc
pow.cc
int pow(int , int);
int main()
{
int r=3;
int a1=pow(3,3);
int a2=pow(3);
return 0;
}
// a1=27
// a2=9
int pow (int a, int k=2)
{
if (k==2) return a*a;
else return a*pow(a, k-1);
}
Argomento di default
• Solo ai parametri più a destra nella calling
sequence può essere dato un default.
8
Overloading
• Funzioni diverse possono avere lo stesso nome
• La funzione che viene chiamata è scelta dal
compilatore in base al tipo di ritorno ed al
numero e tipo degli argomenti
average_array.cc
double media_array(const int a[], int size)
{
int sum=0;
for (int i=0;i<size;i++) sum+=a[i];
return double(sum)/size;
}
double media_array(const double a[], int size)
{
double sum=0;
for (int i=0;i<size;i++) sum+=a[i];
return sum/size;
}
9
Overloading (2)
• La lista dei tipi degli argomenti di una funzione è
chiamata signature
• Il tipo ritornato dalla funzione non fa parte della
signature, mentre il numero e l’ordine degli
argomenti è cruciale
void print(int i=0) {. . .}
// (1)
void print(int i, double x) {. . .} // (2)
void print(double y, int i) {. . .} // (3)
. . .
print(‘A’);
// ‘A’ e` convertito a int, chiama (1)
print(str[]); // errore! Non e` possibile una conversione
print(15,9);
// errore! Ambiguita` fra (2) e (3)
print(15,9.); // OK, chiama (2)
print();
// OK, chiama (1) con il default
10
L’algoritmo di selezione
Ricerca della corrispondenza esatta
Promozioni standard degli argomenti
int long
Conversioni standard dei tipi
int float
Conversioni definite dall’utente
traccia int
• L’utente può sempre utilizzare una conversione
forzata (type cast) per ottenere una corrispondenza
• Il compilatore segnala tutti i casi in cui esiste
ambiguità
11