Overload delle funzioni
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 57 di 104.
L'overload delle funzioni ti permette di definire più funzioni con lo stesso nome ma con elenchi di parametri diversi. Il compilatore seleziona la versione corretta in base agli argomenti che passi. Questa è una forma fondamentale di polimorfismo a tempo di compilazione.
Perché l'overloading funzioni, le funzioni devono differire nella loro firma: nel numero di parametri, nei loro tipi o in entrambi:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
Calculator calc;
calc.add(5, 3); // Chiama add(int, int)
calc.add(2.5, 3.7); // Chiama add(double, double)
calc.add(1, 2, 3); // Chiama add(int, int, int)Il compilatore esamina ogni chiamata e la associa all'overload appropriato. Questo avviene interamente in fase di compilazione, quindi non c'è alcun overhead a runtime.
Importante: Il solo tipo di ritorno non distingue le funzioni sovraccaricate. Quanto segue causerebbe un errore del compilatore:
int getValue();
double getValue(); // Errore: non è possibile sovraccaricare una funzione basandosi solo sul tipo restituitoL'overloading delle funzioni rende il tuo codice più intuitivo. Invece di creare nomi separati come addInts, addDoubles e addThreeInts, usi un unico nome significativo e lasci che il compilatore si occupi del resto.
Sfida
FacileCreiamo una classe formattatrice di messaggi che dimostri la potenza dell’overloading delle funzioni. Creerai una classe Formatter con più metodi format() che gestiscono diversi tipi di input, consentendo al compilatore di scegliere la versione corretta in base a ciò che passi.
Organizzerai il codice in due file:
Formatter.h: definisci una classeFormattercon metodiformat()sovraccaricati che gestiscono diversi scenari:- Un metodo che accetta una singola
std::stringe stampa:Message: <text> - Un metodo che accetta una
std::stringe un livello di prioritàint, stampando:[Priority <priority>] <text> - Un metodo che accetta una
std::stringe un timestampdouble, stampando:[<timestamp>s] <text> - Un metodo che accetta tre parametri
std::string(mittente, destinatario, messaggio) e stampa:From <sender> to <receiver>: <message>
format(): il compilatore selezionerà quello corretto in base agli argomenti.- Un metodo che accetta una singola
main.cpp: leggi quattro input (ciascuno su una riga separata):- Un semplice testo del messaggio
- Un livello di priorità (intero)
- Un timestamp (double)
- Il nome di un mittente
Crea un oggetto
Formattere dimostra tutti e quattro i metodi sovraccaricati:- Chiama
format()passando solo il testo del messaggio - Chiama
format()passando il testo del messaggio e la priorità - Chiama
format()passando il testo del messaggio e il timestamp - Chiama
format()passando il mittente, "Admin" come destinatario e il testo del messaggio
Per esempio, con gli input System ready, 3, 12.5 e Server:
Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System readyNota come chiami lo stesso nome di metodo format() quattro volte, ma ogni chiamata invoca una versione diversa in base al tipo e al numero di argomenti. Questa è la polimorfia a tempo di compilazione in azione: il compilatore determina quale overload usare prima ancora che il programma venga eseguito.
Provalo tu
#include <iostream>
#include <string>
#include "Formatter.h"
using namespace std;
int main() {
// Leggi gli input
string message;
getline(cin, message);
int priority;
cin >> priority;
double timestamp;
cin >> timestamp;
cin.ignore();
string sender;
getline(cin, sender);
// TODO: Crea un oggetto Formatter
// TODO: Chiama format() usando solo il testo del messaggio
// TODO: Chiama format() con il testo del messaggio e priority
// TODO: Chiama format() con il testo del messaggio e timestamp
// TODO: Chiama format() con sender, "Admin" come destinatario e il testo del messaggio
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniBuild e compilazione in C++File header e file sorgenteNamespace e ambitoIntroduzione alla programmazione orientata agli oggetti in C++Classi e oggetti a confrontoIl puntatore 'this'Metodi (funzioni membro)Attributi (membri dati)Fondamenti di costruttori e distruttoriRiepilogo - Calcolatrice semplice4Proprietà delle classi
Membri di istanza e staticiGetter e setterFunzioni membro constParola chiave mutableMetodi e variabili staticiFunzioni e classi friendRiepilogo - Gestore di conti bancari7Ereditarietà
Ereditarietà di baseLivelli di accesso nell’ereditarietàOrdine di chiamata di costruttori e distruttoriRidefinizione dei metodiFunzioni virtuali e VTableEreditarietà multiplaEreditarietà virtualeRiepilogo - Gerarchia dei dipendenti2Gestione della memoria
Memoria Stack vs HeapPuntatori e riferimentiMemoria dinamica (new/delete)Puntatori intelligenti in C++RAII in C++Riepilogo - Gestore di array dinamico5Incapsulamento
Specificatori di accesso in C++Specificatori di accesso in dettaglioOccultamento delle informazioniStruct vs classClassi annidate e interneRiepilogo - Sistema di registrazione degli studenti8Polimorfismo
Polimorfismo a compile time e a runtimeOverload delle funzioniFunzioni virtuali: ripassoFunzioni virtuali pureClassi astratteProgettazione delle interfacce in C++Dynamic casting e RTTIRipasso: calcolatrice di forme11Concetti avanzati di OOP
Composizione vs ereditarietàMixin tramite CRTPIdiom PimplType ErasureEnum class e tipizzazione forteGestione delle eccezioni in OOPGerarchie personalizzate di eccezioni14Pattern di progettazione - Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeRAII come pattern3Costruttori e distruttori
Costruttore predefinitoCostruttore con parametriCostruttore di copiaCostruttore di spostamentoListe di inizializzazione dei costruttoriCostruttori delegantiApprofondimento sui distruttoriRegola del Tre / Cinque / ZeroRipasso - classe String6Sovraccarico degli operatori
Introduzione al sovraccarico degli operatoriSovraccarico degli operatori aritmeticiSovraccarico degli operatori di confrontoOperatori di flussoSovraccarico dell'operatore di assegnazioneSovraccarico degli operatori [] e ()Operatori di conversione di tipoRipasso - Classe Matrix9Template
Template di funzioneTemplate di classeSpecializzazione dei templateTemplate variadiciBasi di SFINAE e dei trait di tipoRiepilogo - Contenitore genericoEsercitati da solo: Compilatore C++ online