Funktionsüberladung
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 57 von 104.
Funktionsüberladung ermöglicht es Ihnen, mehrere Funktionen mit demselben Namen, aber unterschiedlichen Parameterlisten zu definieren. Der Compiler wählt die korrekte Version basierend auf den Argumenten aus, die Sie übergeben. Dies ist eine wichtige Form des Polymorphismus zur Kompilierzeit.
Damit Überladung funktioniert, müssen sich Funktionen in ihrer Signatur unterscheiden – der Anzahl der Parameter, ihren Typen oder beidem:
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); // Ruft add(int, int) auf
calc.add(2.5, 3.7); // Ruft add(double, double) auf
calc.add(1, 2, 3); // Ruft add(int, int, int) aufDer Compiler prüft jeden Aufruf und ordnet ihn der entsprechenden Überladung zu. Dies geschieht vollständig zur Kompilierzeit, sodass kein Laufzeit-Overhead entsteht.
Wichtig: Der Rückgabetyp allein unterscheidet überladene Funktionen nicht. Das Folgende würde zu einem Compilerfehler führen:
int getValue();
double getValue(); // Fehler: Überladung nur durch den Rückgabetyp ist nicht möglichFunktionsüberladung macht Ihren Code intuitiver. Anstatt separate Namen wie addInts, addDoubles und addThreeInts zu erstellen, verwenden Sie einen einzigen aussagekräftigen Namen und lassen den Compiler den Rest erledigen.
Aufgabe
EinfachLassen Sie uns eine Nachrichtenformatierer-Klasse erstellen, die die Leistungsfähigkeit der Funktionsüberladung demonstriert. Sie werden eine Formatter-Klasse mit mehreren format()-Methoden erstellen, die verschiedene Arten von Eingaben verarbeiten, sodass der Compiler die richtige Version basierend auf den übergebenen Argumenten auswählt.
Sie werden Ihren Code auf zwei Dateien aufteilen:
Formatter.h: Definieren Sie eineFormatter-Klasse mit überladenenformat()-Methoden, die verschiedene Szenarien abdecken:- Eine Methode, die einen einzelnen
std::stringentgegennimmt und Folgendes ausgibt:Message: <text> - Eine Methode, die einen
std::stringund eineint-Prioritätsstufe entgegennimmt und Folgendes ausgibt:[Priority <priority>] <text> - Eine Methode, die einen
std::stringund einendouble-Zeitstempel entgegennimmt und Folgendes ausgibt:[<timestamp>s] <text> - Eine Methode, die drei
std::string-Parameter (Absender, Empfänger, Nachricht) entgegennimmt und Folgendes ausgibt:From <sender> to <receiver>: <message>
format()heißen — der Compiler wird die korrekte Methode basierend auf den Argumenten auswählen.- Eine Methode, die einen einzelnen
main.cpp: Lesen Sie vier Eingaben ein (jede in einer separaten Zeile):- Einen einfachen Nachrichtentext
- Eine Prioritätsstufe (Ganzzahl)
- Einen Zeitstempel (Double)
- Einen Absendernamen
Erstellen Sie ein
Formatter-Objekt und demonstrieren Sie alle vier überladenen Methoden:- Rufen Sie
format()nur mit dem Nachrichtentext auf - Rufen Sie
format()mit dem Nachrichtentext und der Priorität auf - Rufen Sie
format()mit dem Nachrichtentext und dem Zeitstempel auf - Rufen Sie
format()mit dem Absender, "Admin" als Empfänger und dem Nachrichtentext auf
Zum Beispiel mit den Eingaben System ready, 3, 12.5 und Server:
Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System readyBeachten Sie, wie Sie denselben Methodennamen format() viermal aufrufen, aber jeder Aufruf eine andere Version basierend auf den Argumenttypen und der Anzahl aufruft. Dies ist Polymorphie zur Kompilierzeit in Aktion — der Compiler bestimmt, welche Überladung verwendet werden soll, noch bevor das Programm ausgeführt wird.
Spickzettel
Funktionsüberladung ermöglicht es Ihnen, mehrere Funktionen mit demselben Namen, aber unterschiedlichen Parameterlisten zu definieren. Der Compiler wählt basierend auf den beim Kompilieren übergebenen Argumenten die korrekte Version aus.
Funktionen müssen sich in ihrer Signatur unterscheiden – der Anzahl der Parameter, ihren Typen oder beidem:
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); // Calls add(int, int)
calc.add(2.5, 3.7); // Calls add(double, double)
calc.add(1, 2, 3); // Calls add(int, int, int)Wichtig: Der Rückgabetyp allein reicht nicht aus, um überladene Funktionen zu unterscheiden:
int getValue();
double getValue(); // Error: cannot overload by return type onlyFunktionsüberladung ist eine Form des Polymorphismus zur Kompilierzeit ohne Overhead zur Laufzeit.
Probier es selbst
#include <iostream>
#include <string>
#include "Formatter.h"
using namespace std;
int main() {
// Eingaben lesen
string message;
getline(cin, message);
int priority;
cin >> priority;
double timestamp;
cin >> timestamp;
cin.ignore();
string sender;
getline(cin, sender);
// TODO: Ein Formatter-Objekt erstellen
// TODO: format() nur mit dem Nachrichtentext aufrufen
// TODO: format() mit Nachrichtentext und priority aufrufen
// TODO: format() mit Nachrichtentext und timestamp aufrufen
// TODO: format() mit sender, "Admin" als Empfänger und Nachrichtentext aufrufen
return 0;
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienC++ Build & KompilierungHeader-Dateien & QuelldateienNamensräume & GültigkeitsbereicheEinführung in OOP in C++Klassen vs. ObjekteDer 'this'-PointerMethoden (Elementfunktionen)Attribute (Datenelemente)Grundlagen zu Ctors & DtorsRückblick - Einfacher Taschenrechner4Klasseneigenschaften
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen & KlassenZusammenfassung - Bankkonto-Manager7Vererbung
Grundlagen der VererbungZugriffsstufen bei VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick - Mitarbeiter-Hierarchie2Speicherverwaltung
Stack vs. Heap SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Smart Pointers in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsspezifizierer in C++Zugriffsspezifizierer im DetailInformation HidingStruct vs. ClassVerschachtelte & innere KlassenRückblick - Studentenverwaltungssystem8Polymorphie
Kompilierzeit- vs. Laufzeit-PolymorphieFunktionsüberladungVirtuelle Funktionen – WiederholungRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIZusammenfassung – Formen-Rechner3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorVerschiebekonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktoren im DetailRule of Three / Five / ZeroZusammenfassung - String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladen der [] und () OperatorenTypumwandlungsoperatorenRückblick - Matrix-Klasse9Templates
FunktionstemplatesKlassentemplatesTemplate-SpezialisierungVariadische TemplatesSFINAE & Type Traits GrundlagenRückblick - Generische Container