Le funzioni in C++
Una funzione è un blocco di codice dotato di un nome, che raggruppa un insieme di istruzioni con uno scopo preciso. Le funzioni permettono di suddividere un programma in parti più piccole e gestibili, di evitare la ripetizione del codice e di nascondere i dettagli implementativi dietro un'interfaccia chiara. Ogni programma C++ ne contiene almeno una, la funzione main, ma la potenza del linguaggio si esprime quando si definiscono funzioni proprie per organizzare la logica.
Definizione di una funzione
Una funzione è composta da un tipo di ritorno, un nome, una lista di parametri tra parentesi e un corpo racchiuso tra parentesi graffe. Il tipo di ritorno indica la natura del valore che la funzione restituisce; se la funzione non restituisce nulla, si utilizza il tipo speciale void.
#include <iostream>
// Funzione che calcola la somma di due interi
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(4, 7); // Chiamata della funzione
std::cout << result << std::endl;
return 0;
}
Quando si chiama una funzione, i valori passati tra parentesi vengono detti argomenti e vengono associati ai rispettivi parametri. L'istruzione return termina la funzione e ne restituisce il risultato al punto in cui è stata chiamata.
Dichiarazione e definizione
In C++ una funzione deve essere conosciuta dal compilatore prima di poter essere chiamata. È possibile dichiarare la funzione fornendone soltanto il prototipo, cioè la firma senza corpo, e definirla altrove. Questa separazione è alla base dell'organizzazione del codice in file di intestazione e file di implementazione.
// Dichiarazione: il prototipo comunica l'esistenza della funzione
double computeArea(double width, double height);
int main() {
double area = computeArea(3.0, 5.0);
return 0;
}
// Definizione: contiene l'implementazione effettiva
double computeArea(double width, double height) {
return width * height;
}
Passaggio per valore e per riferimento
Per impostazione predefinita, gli argomenti vengono passati per valore: la funzione riceve una copia dei dati, e qualsiasi modifica al parametro non si riflette sulla variabile originale. Quando si desidera che la funzione possa modificare la variabile chiamante, oppure si vuole evitare la copia di dati di grandi dimensioni, si usa il passaggio per riferimento, indicato dal simbolo & accanto al tipo del parametro.
// Passaggio per valore: l'originale non viene modificato
void tryToReset(int number) {
number = 0;
}
// Passaggio per riferimento: l'originale viene modificato
void reset(int& number) {
number = 0;
}
Quando si passa un oggetto per riferimento solo per evitarne la copia, ma senza intenzione di modificarlo, è buona pratica aggiungere const davanti al tipo. In questo modo si comunica chiaramente che la funzione non altererà l'argomento e si ottiene un riferimento costante.
#include <string>
// Riferimento costante: efficiente e sicuro
void greet(const std::string& name) {
std::cout << "Ciao, " << name << std::endl;
}
Argomenti predefiniti
È possibile assegnare un valore predefinito a uno o più parametri di una funzione. Se al momento della chiamata l'argomento corrispondente viene omesso, viene utilizzato il valore predefinito. I parametri con valore predefinito devono trovarsi sempre alla fine della lista dei parametri.
// Il parametro base ha un valore predefinito
int power(int exponent, int base = 2) {
int result = 1;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
// power(3) usa base 2 e vale 8; power(3, 10) vale 1000
Overloading delle funzioni
Il C++ consente di definire più funzioni con lo stesso nome, purché differiscano per numero o tipo dei parametri. Questa caratteristica, detta overloading, permette di esprimere operazioni concettualmente simili con un'unica denominazione, lasciando al compilatore il compito di scegliere la versione corretta in base agli argomenti forniti.
// Stessa operazione concettuale su tipi diversi
int maximum(int a, int b) {
return (a > b) ? a : b;
}
double maximum(double a, double b) {
return (a > b) ? a : b;
}
Nell'esempio è comparso anche l'operatore ternario ? :, una forma compatta dell'istruzione condizionale che restituisce un valore in base a una condizione. Le funzioni, con i loro parametri e le loro varianti, sono lo strumento principale per strutturare programmi leggibili e manutenibili. Nei prossimi articoli vedremo come gestire collezioni di dati e come introdurre la programmazione orientata agli oggetti.