Strukturierte Bindungen
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 88 von 104.
Strukturierte Bindungen, die in C++17 eingeführt wurden, ermöglichen es dir, mehrere Werte aus Arrays, Paaren, Tupeln oder Strukturen in einer einzigen Deklaration in einzelne benannte Variablen zu entpacken. Dadurch wird der Code bei der Arbeit mit zusammengesetzten Daten übersichtlicher und besser lesbar.
Die Syntax verwendet auto mit eckigen Klammern, die die neuen Variablennamen enthalten:
#include <iostream>
#include <map>
#include <tuple>
int main() {
// Entpacken eines Paars
std::pair<std::string, int> person{"Alice", 25};
auto [name, age] = person;
std::cout << name << " is " << age << "\n";
// Entpacken eines Tuples
std::tuple<int, double, char> data{42, 3.14, 'X'};
auto [num, pi, letter] = data;
// Entpacken in bereichsbasierten for-Schleifen
std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
for (const auto& [student, score] : scores) {
std::cout << student << ": " << score << "\n";
}
}Strukturierte Bindings funktionieren auch mit Arrays und benutzerdefinierten Structs, die öffentliche Member haben:
struct Point {
double x;
double y;
};
Point getOrigin() { return {0.0, 0.0}; }
int main() {
auto [x, y] = getOrigin();
int arr[3] = {1, 2, 3};
auto [a, b, c] = arr;
}Du kannst auto& oder const auto& verwenden, um per Referenz zu binden, Kopien zu vermeiden und bei Bedarf die ursprünglichen Werte zu ändern. Diese Funktion ist besonders nützlich, wenn du über STL-Container iterierst oder Funktionen behandelst, die mehrere Werte zurückgeben.
Aufgabe
EinfachErstellen wir einen Studentennoten-Analyzer, der die Leistungsfähigkeit strukturierter Bindungen demonstriert. Du erstellst ein System, das Studentendatensätze und Kursdaten verarbeitet und strukturierte Bindungen verwendet, um Paare, Tupel und Strukturen in deinem gesamten Code elegant zu entpacken.
Du organisierst deinen Code über drei Dateien:
Student.h: Definiere eineStudent-Struktur mit öffentlichen Membern für den Namen des Studenten (std::string), die ID (int) und den GPA (double). Erstelle außerdem eine Funktion namenscreateStudent, die einen Namen, eine ID und einen GPA entgegennimmt und eineStudent-Struktur zurückgibt.GradeUtils.h: Erstelle Hilfsfunktionen für die Notenverarbeitung.Definiere eine Funktion
getGradeInfo, die eine numerische Punktzahl (Ganzzahl) entgegennimmt und einstd::tuplemit drei Werten zurückgibt: die Buchstabennote (std::string), die Notenpunkte (double) und die Information, ob die Leistung bestanden ist (bool). Verwende diese Bewertungsskala:- 90+ : "A", 4.0, true
- 80-89: "B", 3.0, true
- 70-79: "C", 2.0, true
- 60-69: "D", 1.0, true
- Unter 60: "F", 0.0, false
Definiere außerdem eine Funktion
makeScorePair, die einen Kursnamen (std::string) und eine Punktzahl (int) entgegennimmt und einstd::pairmit diesen Werten zurückgibt.main.cpp: Lies vier Eingaben ein:- Name des Studenten (String)
- Studenten-ID (Ganzzahl)
- Kursname (String)
- Punktzahl (Ganzzahl)
Verwende strukturierte Bindungen in deiner gesamten Main-Funktion:
- Rufe
createStudentmit dem Namen, der ID und einem Platzhalter-GPA von 0.0 auf. Verwende strukturierte Bindungen, um die zurückgegebene Struktur in einzelne Variablen zu entpacken, und gib anschließend Folgendes aus:Student: [name] (ID: [id]) - Rufe
makeScorePairmit dem Kursnamen und der Punktzahl auf. Verwende strukturierte Bindungen, um das Paar zu entpacken, und gib anschließend Folgendes aus:Course: [course], Score: [score] - Rufe
getGradeInfomit der Punktzahl auf. Verwende strukturierte Bindungen, um alle drei Tupelelemente zu entpacken, und gib anschließend Folgendes aus:(Gib "yes" aus, wenn passing true ist, und "no", wenn es false ist.)Grade: [letter] Points: [points] Passing: [yes/no]
Beispielsweise mit den Eingaben Alice, 1001, Math und 85:
Student: Alice (ID: 1001)
Course: Math, Score: 85
Grade: B
Points: 3
Passing: yesMit den Eingaben Bob, 2002, Physics und 55:
Student: Bob (ID: 2002)
Course: Physics, Score: 55
Grade: F
Points: 0
Passing: noDenke daran, bei Bedarf <tuple> und <utility> einzubinden. Die zentrale Erkenntnis ist, wie strukturierte Bindungen es dir ermöglichen, zusammengesetzte Typen, Paare, Tupel und Strukturen in einer einzigen, gut lesbaren Deklaration in benannte Variablen zu entpacken.
Probier es selbst
#include <iostream>
#include <string>
#include "Student.h"
#include "GradeUtils.h"
int main() {
// Eingaben lesen
std::string studentName;
int studentId;
std::string courseName;
int score;
std::cin >> studentName;
std::cin >> studentId;
std::cin >> courseName;
std::cin >> score;
// TODO: Rufe createStudent mit name, id und Platzhalter-GPA von 0.0 auf
// Verwende strukturierte Bindungen, um die Struct zu entpacken: auto [name, id, gpa] = ...
// Ausgeben: Student: [name] (ID: [id])
// TODO: Rufe makeScorePair mit Kursname und score auf
// Verwende strukturierte Bindungen, um das Paar zu entpacken: auto [course, sc] = ...
// Ausgeben: Course: [course], Score: [score]
// TODO: Rufe getGradeInfo mit dem score auf
// Verwende strukturierte Bindungen, um das Tupel zu entpacken: auto [letter, points, passing] = ...
// Ausgeben:
// Grade: [letter]
// Points: [points]
// Passing: [yes/no] (drucke "yes", wenn passing true ist, "no", wenn false)
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 & QuelldateienNamespaces & GültigkeitsbereichEinführung in OOP mit C++Klassen vs. ObjekteDer „this“-ZeigerMethoden (Member-Funktionen)Attribute (Datenmember)Grundlagen zu Ctors & DtorsRückblick – Einfacher Taschenrechner4Klassenattribute
Instanz- vs. statische MemberGetter und SetterConst-MemberfunktionenMutable-SchlüsselwortStatische Methoden und VariablenFriend-Funktionen und -KlassenZusammenfassung – Bankkontoverwaltung7Vererbung
Grundlagen der VererbungZugriffsebenen bei der VererbungAufrufreihenfolge von Ctor & DtorÜberschreiben von MethodenVirtuelle Funktionen & VTableMehrfachvererbungVirtuelle VererbungRückblick – Mitarbeiterhierarchie2Speicherverwaltung
Stack- vs. Heap-SpeicherZeiger und ReferenzenDynamischer Speicher (new/delete)Intelligente Zeiger in C++RAII in C++Rückblick – Dynamischer Array-Manager5Kapselung
Zugriffsbezeichner in C++Zugriffsbezeichner im DetailInformationsverbergungStruct vs. KlasseVerschachtelte und innere KlassenWiederholung – Studierendenverwaltungssystem8Polymorphie
Polymorphie zur Compilezeit vs. LaufzeitFunktionsüberladungVirtuelle Funktionen erneut betrachtetRein virtuelle FunktionenAbstrakte KlassenInterface-Design in C++Dynamic Casting & RTTIRückblick – Shape-Calculator3Konstruktoren & Destruktoren
StandardkonstruktorParametrisierter KonstruktorKopierkonstruktorMove-KonstruktorKonstruktor-InitialisierungslistenDelegierende KonstruktorenDestruktor im DetailDrei-/Fünf-/Null-RegelZusammenfassung – String-Klasse6Operatorüberladung
Einführung in die OperatorüberladungArithmetische OperatorüberladungVergleichsoperatorüberladungStream-OperatorenZuweisungsoperatorüberladungÜberladung der Operatoren [] und ()TypkonvertierungsoperatorenWiederholung – Matrix-Klasse9Templates
FunktionstemplatesKlassen-TemplatesTemplate-SpezialisierungVariadische TemplatesGrundlagen zu SFINAE und Type TraitsRückblick – Generischer Container12Moderne C++-Funktionen
Move-Semantik & RvaluesPerfektes ForwardingLambda-Ausdrücke im Detailstd::function & std::bindconstexpr und constevalStrukturierte Bindungenoptional, variant, anyÜbe selbstständig: Online-C++-Compiler