ProgrammazioneIngegnere C++

Spiega come funzionano il sovraccarico e i valori predefiniti per le funzioni membro della classe in C++. Quali sono le sottigliezze dell'uso congiunto delle funzioni sovraccaricate e dei valori predefiniti?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Il sovraccarico delle funzioni (overloading) è un meccanismo per dichiarare più funzioni con lo stesso nome, ma con firme diverse (numero o tipo di parametri).

I valori predefiniti per i parametri possono essere specificati nella dichiarazione delle funzioni. Sottigliezza: i valori predefiniti vengono considerati solo durante la compilazione della chiamata e vengono inseriti dal compilatore in base alla firma visibile.

Nelle classi si incontra spesso la situazione:

class Printer { void print(int n, char c = '*') { /* ... */ } void print(const std::string& s) { /* ... */ } }; Printer p; p.print(5); // chiamerà print(int n, char c = '*'), c = '*' p.print("Hi"); // chiamerà print(const std::string&)

Sottigliezze:

  • Non si dovrebbe sovraccaricare una funzione e differenziarla solo tramite valori predefiniti, in quanto ciò porta a ambiguità.
void foo(int x, int y = 10); void foo(int x); foo(1); // Errore: non è chiaro quale funzione chiamare

Domanda insidiosa.

Qual è l'unico posto in cui è consentito specificare un valore predefinito per una funzione membro della classe?

Risposta: Il valore predefinito per il metodo di una classe può essere specificato nella dichiarazione del metodo all'interno della classe (o nella prima dichiarazione al di fuori della classe), ma non è consentito specificarlo sia nella classe che nell'implementazione. Altrimenti si verificherà un errore di ridichiarazione.

class X { void func(int x = 5); // Qui è possibile }; void X::func(int x) { /* ... */ } // Ma non qui!

Esempi di errori reali dovuti alla mancanza di conoscenza delle sottigliezze dell'argomento.


Storia 1

Nel software bancario si è verificato un errore durante la fase di compilazione: parte delle funzioni sovraccaricate con valori predefiniti diversi ostacolavano la scelta univoca di quella necessaria, le chiamate erano ambigue durante la compilazione — risultato, impossibilità di compilare il rilascio fino alla correzione delle modifiche manuali.


Storia 2

Nella squadra era diffuso uno stile in cui tutti i valori predefiniti venivano spostati nell'implementazione e non nell'intestazione della classe, tuttavia per alcuni metodi delle classi ciò causava disallineamenti tra interfaccia e implementazione — diverse TU vedevano diversi parametri della funzione, portando a strani bug di compilazione e run-time.


Storia 3

Nell'espansione di una libreria pubblica è stato erroneamente aggiunto un sovraccarico della funzione con gli stessi parametri, ma con valori predefiniti diversi. Il compilatore ha iniziato a restituire ambiguità durante le chiamate API, e gli utenti si sono trovati di fronte a chiamate obsolete e problemi di compatibilità binaria.