next up previous contents index
Next: Ancora sulle funzioni Up: Funzioni Previous: Introduzione alle funzioni   Indice   Indice analitico

Funzioni in C++

Vediamo nel presente paragrafo come creare funzioni nei nostri programmi C++. Ogni funzione utilizza come nome un identificatore, il quale rispetta le stesse regole delle variabili; le caratteristiche essenziali di una funzione sono il tipo di ritorno e gli argomenti. Il tipo di ritorno è il tipo di dato che la funzione ritorna; nel caso la funzioni non ritorni nessun dato, viene specifiticato come tipo di ritorno void. Gli argomenti di una funzione sono i tipi di dato che la funzione accetta in entrata. Vediamo la sintassi della definizione di funzione:
tipoRitorno nomeFunzione (arg1, arg2, ..., argN) { /* ...*/ }
ove arg1, ..., argN sono $N$ dichiarazioni di variabili. Note: gli argomenti di una funzione potrebbero anche essere assenti; non è possibile utilizzare una sintassi abbreviata per la dichiarazione degli argomenti nella definizione delle funzioni (vd. esempi successivi); il corpo principale di qualunque programma C++ è una funzione di nome main che, negli esempi fino ad ora considerati, non torna nessun valore (è dunque una funzione void) e non ha argomenti. All'interno di una funzione deve essere presente lo statement che stabilisce il ritorno di un risultato da parte di essa: si tratta dello statement return, seguito dal risultato da tornare, che deve essere dello stesso tipo del tipo di ritorno della funzione (ovviamente); se la funzione è void allora lo statement return non è obbligatorio, ma può comunque essere utilizzato per interrompere il normale flusso di esecuzione della funzione. Vediamo qualche esempio.


// ex4_4_1.cpp
#include <iostream.h>

//  int max (int a, b) {  // NO: bisogna dichiarare gli
//    /* ...  */          // argomenti delle funzioni  
//  }                     // per esteso

int max (int a, int b) {
  if (a >= b)
    return a;
  return b;
}

void main() {
  int a, b;
  cout << "a? "; cin >> a;
  cout << "b? "; cin >> b;
  int m = max (a, b);
  cout << "max: " << m;
}

Si noti innanzitutto che abbiamo definito la funzione max prima del corpo principale; se avessimo voluto definirla dopo di esso, avremmo dovuto dichiararla comunque prima di tale blocco. Qual è la differenza tra dichiarare e definire una funzione? Nella dichiarazione di una funzione si danno solo le informazioni strettamente necessaria: tipo del ritorno e tipo degli argomenti, mentre definire una funzione vuol dire scrivere il suo corpo, e quindi dare anche un nome agli argomenti. Il seguente esempio è del tutto equivalente al precedente:


// ex4_4_2.cpp
#include <iostream.h>

int max (int, int);            // dichiarazione

void main() {
  int a, b;
  cout << "a? "; cin >> a;
  cout << "b? "; cin >> b;
  int m = max (a, b);
  cout << "max: " << m;
}

int max (int a, int b) {       // definizione
  if (a >= b)
    return a;
  return b;
}

In entrambi gli esempi del presente paragrafo abbiamo utilizzato gli stessi identificatori per le variabili all'interno del corpo principale e per quelle interne alle funzioni; i programmi risultano corretti, sebbene sappiamo che non è possibile usare un identificatore già esistente, perché le funzioni, così come i blocchi, hanno una vita ``parallela'' a quella del programma principale: possono ad esempio permettersi di avere gli stessi nomi per le variabili.

Ci poniamo adesso un problema, che prima della presentazione delle funzioni poteva non avere senso: è possibile dichiarare una variabile esternamente a tutte le funzioni, compresa il corpo principale? La risposta è affermativa: si tratta in tal caso di variabili globali, le quali valgono in tutte le funzioni. Analogamente è possibile dichiarare delle costanti globali.


// ex4_4_3.cpp
#include <iostream.h>

const double PIGRECO = 3.141592;
double circ;

double circonferenza (double raggio) {
  // circ appartiene alla funzione
  double circ = raggio * 2 * PIGRECO;
  return circ;
}

void stampaCirconferenza () {
  cout << "cinconferenza: " << circ;   // e' la circ globale
}
void main() {
  double raggio;
  cout << "raggio? "; cin >> raggio;
  circ = circonferenza (raggio);       // e' la circ globale
  stampaCirconferenza();
}

Si noti in questo esempio come l'identificatore circ assuma un significato diverso a seconda della funzione nella quale si trovi: in generale esso è riferito ad una variabile globale di tipo double, tuttavia nella funzione circonferenza, siccome viene dichiarata una nuova variabile circ di tipo double, la variabile globale risulta nascosta. Questo modo di procedere è evidentemente molto scomodo, nonché pericoloso; è infatti facile confondere una variabile per un'altra, specialmente in programmi corposi; si cerchi pertanto di utilizzare il meno possibile le variabili globali. Vediamo il seguente:


// ex4_4_4.cpp
#include <iostream.h>

// calcola il massimo comun divisore tra due numeri
// sfruttando il cosiddetto algoritmo di Euclide
int mcd (int a, int b) {
  while (a != b)
    if (a > b)
      a -= b;
    else
      b -= a;
  return a;
}

// calcola il minimo comune multiplo tra due numeri
// sfruttando il fatto che esso e' uguale al prodotto
// dei due numeri diviso il loro massimo comun divisore
int mcm (int a, int b) {
  int m = (a * b) / mcd(a, b);
  return m;
}

void stampa (int i) {
  switch (i) {
  case 1:       // messaggio di benvenuto
    cout << "questo programma calcola\n"
      "il massimo comun divisore\n"
      " e il minimo comune multiplo\n"
      "tra due numeri interi\n\n";
    return;
  case 2:       // messaggio di arrivedersi
    cout << "bye bye!";
    return;
  default:
    return;
  }
  cout << "AHHHHHH";  // non viene mai stampato
}

void main () {
  int a, b;
  stampa (1);    // benvenuto
  cout << "a? "; cin >> a;
  cout << "b? "; cin >> b;
  cout << "mcm: " << mcm(a,b) << '\n';
  cout << "mcd: " << mcd(a,b) << '\n';
  stampa (2);    // arrivederci
}

esempio di output:
questo programma calcola
il massimo comun divisore
e il minimo comune multiplo
tra due numeri interi

a? 30
b? 45
mcm: 90
mcd: 15
bye bye!

Si noti che nella funzione void stampa(int) abbiamo utilizzato la parola chiave return al posto del classico break; mentre quest'ultimo ci avrebbe fatti uscire semplicemente dallo switch, e quindi il programma avrebbe stampato anche AHHHHHHH, utilizzando return il flusso di esecuzione torna al programma principale, così come era nostra intenzione che fosse.

ex-2
si scriva un programma che trovi il minimo comune multiplo di tre interi, immessi dall'utente;
ex-3
si scriva un programma che elenchi i divisori di un numero intero


next up previous contents index
Next: Ancora sulle funzioni Up: Funzioni Previous: Introduzione alle funzioni   Indice   Indice analitico
Claudio Cicconetti
2000-09-06