Modificatori e Tipi di Ritorno
Le funzioni in C++ servono a incapsulare la logica.
“Functions should do one thing. They should do it well. They should do it only.” — Robert C. Martin
In questo capitolo scenderemo nei meandri più tecnici delle funzioni e dei concetti funzionali introdotti col C++ moderno.
Modificatori di Funzione (Prefix e Suffix)
Section titled “Modificatori di Funzione (Prefix e Suffix)”La firma di una funzione in C++ può essere adornata da molteplici keyword. Alcune vanno prima del tipo di ritorno (prefix), altre in coda (suffix). Non c’è una logica linguistica assoluta dietro questa suddivisione, è unicamente frutto dell’evoluzione storica del linguaggio.
Modificatori di Prefisso (Prefix)
Section titled “Modificatori di Prefisso (Prefix)”Abbiamo già incontrato:
static: Se usato su funzioni libere, indica un Internal Linkage (la funzione è visibile solo all’interno del suo file.cpp). Se usato sui metodi di classe, slega il metodo dall’istanza.virtual: Consente al metodo di essere sovrascritto dalle classi figlie.constexpr: Comunica al compilatore di calcolare la funzione a tempo di compilazione.
Un modificatore critico è inline.
Richiedere che una funzione sia inline suggerisce al compilatore di evitare la vera chiamata a funzione a runtime (che implicherebbe l’uso dei registri, lo stack, il salto e il ritorno), e di letteralmente copia-incollare le istruzioni interne della funzione direttamente nei punti in cui viene invocata nel binario. Migliora le performance sacrificando le dimensioni del file compilato. (I compilatori moderni lo fanno in automatico, ma usarlo negli Header previene errori di definizione multipla).
Modificatori di Suffisso (Suffix)
Section titled “Modificatori di Suffisso (Suffix)”Abbiamo già visto const (la funzione non altera i campi della classe) e noexcept (non lancerà eccezioni).
Ne aggiungiamo due:
final: Esattamente l’opposto divirtual. Blocca definitivamente l’ereditarietà di quel metodo. Nessuna classe figlia potrà mai più sovrascriverlo. Questo agevola la Devirtualization (il compilatore rimuove il sovraccarico dinamico sapendo che la catena si è chiusa).volatile: Usato sui metodi, si comporta comeconst: significa che questo metodo può essere legittimamente invocato su un’istanza dell’oggetto dichiarata come volatile (e quindi non sarà ottimizzata via).
Tipi di Ritorno Dedotti (auto e decltype)
Section titled “Tipi di Ritorno Dedotti (auto e decltype)”Nelle funzioni ordinarie sappiamo già quale tipo vogliamo restituire. Tuttavia, quando costruiamo Funzioni Template generiche, il tipo di ritorno può dipendere interamente dalla “matematica” fatta tra i due parametri astratti!
Come fai a dichiarare il tipo di ritorno di add(T1 a, T2 b) se non sai se T1 è un intero e T2 un double? Usi auto.
Il compilatore dedurrà da sé il risultato.
Storicamente, si usava (e si usa in metaprogrammazione fitta) il potente strumento decltype(espressione). Restituisce il tipo esatto risultante dall’espressione passata tra parentesi senza valutarla.