# Dal C al C++/Utilizzo avanzato di librerie/I parametri di default

Dal C al C++
Copertina Tutti i moduli · Sviluppo
* IntroduzioneDal C al C++/Introduzione
** I destinatari del libroDal C al C++/Introduzione#I destinatari del libro
** La struttura del libroDal C al C++/Introduzione#La struttura del libro
** Impieghi del linguaggioDal C al C++/Introduzione#Impieghi del linguaggio
** PanoramicaDal C al C++/Introduzione#Panoramica
* Utilizzo basilare di librerie
** ArrayDal C al C++/Array
** Il tipo "bool"Dal C al C++/Utilizzo basilare di librerie/Il tipo "bool"
** L'uso di classi e oggettiDal C al C++/Utilizzo basilare di librerie/L'uso di classi e oggetti
** Dichiarazioni e definizioniDal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni
*** Le variabili riferimentoDal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni#Le variabili riferimento
*** Il modificatore "const"Dal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni#Il modificatore "const"
*** Il sovraccaricamentoDal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni#Il sovraccaricamento
*** L'inizializzazione degli oggettiDal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni#L'inizializzazione degli oggetti
*** L'allocazione degli oggettiDal C al C++/Utilizzo basilare di librerie/Dichiarazioni e definizioni#L'allocazione degli oggetti
** L'uso dei templateDal C al C++/Utilizzo basilare di librerie/L'uso dei template
** L'uso dei namespaceDal C al C++/Utilizzo basilare di librerie/L'uso dei namespace
** I file di intestazioneDal C al C++/Utilizzo basilare di librerie/I file di intestazione
** L'uso delle stringheDal C al C++/Utilizzo basilare di librerie/L'uso delle stringhe
** I canali di ingresso/uscitaDal C al C++/Utilizzo basilare di librerie/I canali di ingresso/uscita
** La gestione delle eccezioni
** I contenitori standardDal C al C++/Utilizzo basilare di librerie/I contenitori standard
** Le funzioni standardDal C al C++/Utilizzo basilare di librerie/Le funzioni standard
* Utilizzo avanzato di librerie
** Ridefinizione di funzioni membroDal C al C++/Utilizzo avanzato di librerie/Ridefinizione di funzioni membro
** I parametri di defaultDal C al C++/Utilizzo avanzato di librerie/I parametri di default
** Gli iteratori sui contenitori
** Gli algoritmi sui contenitori
* Creazione di librerie
** Classi isolateDal C al C++/Classi isolate
*** I costruttoriDal C al C++/Classi isolate#I costruttori
*** I distruttoriDal C al C++/Classi isolate#I distruttori
*** Separazione tra interfaccia e implementazioneDal C al C++/Classi isolate#Separazione tra interfaccia e implementazione
** Gerarchie di classiDal C al C++/Gerarchie di classi
** Proprietari di risorse
** Eccezioni
** Namespace
** Template di funzione
** Template di classe
** Algoritmi su sequenze
* La metaprogrammazione
* La progettazione del software
* Gioco life di ConwayDal C al C++/Gioco life di Conway
Modifica il sommario

## I valori di default per i parametri nelle chiamate di funzione
### Motivazione

Una libreria, in un primo tempo, contiene una funzione di grande complessità, dichiarata nel seguente modo:
Il codice applicativo contiene, in numerosi punti, istruzioni come la seguente:
Tale funzione usa internamente un valore costante pari a 4. Un giorno si decide che, per un caso particolare, quella costante interna deve valere 5.
Per evitare di duplicare l'intera funzione, si può trasformate tale costante in un parametro, aggiunto alla lista di parametri della funzione, dichiarandola nel seguente modo:
Nel punto in cui serviva tale funzionalità, la funzione è chiamata con la seguente istruzione:
Tale modifica ha però un inconveniente: in tutti i molteplici punti in cui la vecchia funzione veniva utilizzata, si ha un errore sintattico, in quanto la funzione viene chiamata passando un solo parametro, quando ormai se ne aspetta due. Una modifica di questo tipo a una funzione di libreria, se usata in numerosi programmi, viene detta in inglese "breaking change", cioè "modifica dirompente", in quanto rende illegale o scorretto del codice che prima era legale e corretto.
In linguaggio C, l'unico modo di evitare una modifica dirompente e di duplicare del codice è procedere nel seguente modo. La funzione in cui la costante è diventata un parametro cambia di nome, per esempio dichiarandola nel seguente modo:
Si crea la seguente funzione:
In tal modo, tutti i vecchi utilizzatori di "f", senza saperlo, chiamano la nuova funzione "f2", passandole come parametro il valore che prima era una costante. Gli utilizzatori che volessero utilizzare un valore diverso, possono chiamare direttamente "f2".
In C++, per semplificare tale problematica, è stato introdotto il concetto di "valore di default" per i parametri di funzione. Basta trasformare la vecchia dichiarazione della funzione "f" nella seguente dichiarazione:
Questa dichiarazione permette di chiamare "f" sia con due parametri che con un parametro solo. Chiamandola con un solo parametro, il parametro mancante assumerà il valore indicato dopo il segno "=".

### Regole

Il valore di default può essere un'espressione che possa essere usata per inizializzare una variabile del tipo dichiarato. Per esempio, la seguente dichiarazione di "f1" è valida, mentre quella di "f2" non lo è:
Si possono dichiarare valori di default per più parametri, anche tutti. Ecco un esempio di dichiarazione e di chiamate valide:
Si noti che usando valori di default non si hanno né vantaggi né penalizzazioni prestazionali; è semplicemente un'abbreviazione sintattica.
La seguente dichiarazione è illegale:
Infatti, non è possibile dichiarare un valore di default per un parametro quando per uno o più parametri seguenti non è stato specificato un valore di default.
Inoltre, si consideri la seguente dichiarazione e le successive chiamate a tale funzione
Nella prima chiamata a "f" si specificano entrambi i parametri. Nella seconda chiamata, il programmatore, ritenendo già soddisfacente il valore di default per il primo parametro, si è limitato a specificare il secondo parametro. Tale sintassi è illegale, in quanto i parametri si possono omettere solo progressivamente procedendo da destra a sinistra.
Il senso di ciò è che i parametri aventi valori di default sono stati pensati come parametri facoltativi in aggiunta a quelli obbligatori.
Anche le funzioni membro di una classe o struttura possono avere valori di default per i parametri.
Per esempio, la funzione "substr", della classe standard "string", può essere usata come nel seguente programma:
Questo programma stampa sulla console "de,defgh,abcdefgh,abc.".
La prima chiamata a "substr" specifica sia il punto da cui iniziare la sottostringa da estrarre che la sua lunghezza.
La seconda chiamata specifica solo il punto da cui iniziare la sottostringa, sottintendendo che la lunghezza è infinita. Se la lunghezza specificata per la sottostringa è eccessiva, viene estratta la parte rimanente della stringa.
La terza chiamata non specifica neanche il punto da cui iniziare la sottostringa, sottintendendo l'inizio della stringa originale. Ne risulta che tale chiamata effettua una copia dell'intera stringa.
La quarta chiamata è l'unico modo di estrarre una sottostringa contenente solo i primi tre caratteri, dato che non è possibile specificare la lunghezza della stringa senza specificare il punto iniziale.
Si consideri il seguente codice:
La prima e la seconda riga dichiarano la funzione "f", con quelli che in C si chiamano prototipi di funzione, mentre la terza riga definisce la stessa funzione. Questo codice è illegale, in quanto se una funzione viene prima dichiarata e poi definita, nelle dichiarazioni successive alla prima e nella definizione non sono ammessi parametri di default. Valgono quelli eventualmente specificati nella dichiarazione. La versione corretta è la seguente:
Ecco un esempio di programma completo valido:
Questo programma stampa "3 6".

## I parametri di default nelle istanziazioni di template

Anche per i parametri dei template di classe sono ammessi valori di default, ma non per i template di funzione. Supponiamo di avere la definizione del seguente template di classe:
È possibile istanziare tale template con le seguenti istruzioni:
La prima istruzione definisce la variabile "a1" di tipo "C<int, double>". La seconda istruzione definisce la variabile "a2" di tipo "C<int, int>".
Ecco un altro esempio, in un programma completo:
Questo programma stampa "8 6". Nella prima istanziazione del template di classe "C", il parametro di template "N1" riceve il valore 3 e il parametro "N2" riceve il valore 5, come specificato tra parentesi angolari. La funzione "f" si limita a rendere la somma tra questi due numeri. Nella seconda istanziazione del template di classe "C", il parametro di template "N1" riceve il valore 6, come specificato tra parentesi angolari, mentre il parametro "N2" riceve il valore di default 0.