Wiązania strukturalne
Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 88 z 104.
Wiązania strukturalne, wprowadzone w C++17, pozwalają rozpakować wiele wartości z tablic, par, krotek lub struktur do osobnych nazwanych zmiennych w jednej deklaracji. Dzięki temu kod jest bardziej przejrzysty i czytelny podczas pracy ze złożonymi danymi.
Składnia używa auto z nawiasami kwadratowymi zawierającymi nowe nazwy zmiennych:
#include <iostream>
#include <map>
#include <tuple>
int main() {
// Rozpakowywanie pary
std::pair<std::string, int> person{"Alice", 25};
auto [name, age] = person;
std::cout << name << " is " << age << "\n";
// Rozpakowywanie krotki
std::tuple<int, double, char> data{42, 3.14, 'X'};
auto [num, pi, letter] = data;
// Rozpakowywanie w pętlach for opartych na zakresach
std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
for (const auto& [student, score] : scores) {
std::cout << student << ": " << score << "\n";
}
}Więzy strukturalne działają również z tablicami i własnymi strukturami, które mają publiczne składowe:
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;
}Możesz użyć auto& lub const auto&, aby powiązać przez referencję, unikając kopiowania i umożliwiając modyfikowanie oryginalnych wartości w razie potrzeby. Ta funkcja jest szczególnie przydatna podczas iterowania po kontenerach STL lub obsługi funkcji zwracających wiele wartości.
Wyzwanie
ŁatwyZbudujmy analizator ocen uczniów, który pokazuje możliwości wiązań strukturalnych. Stworzysz system przetwarzający dane uczniów i kursów, wykorzystując wiązania strukturalne do eleganckiego rozpakowywania par, krotek i struktur w całym kodzie.
Rozmieścisz swój kod w trzech plikach:
Student.h: Zdefiniuj strukturęStudentz publicznymi polami zawierającymi imię i nazwisko ucznia (std::string), identyfikator (int) i GPA (double). Utwórz też funkcję o nazwiecreateStudent, która przyjmuje imię i nazwisko, identyfikator oraz GPA, a następnie zwraca strukturęStudent.GradeUtils.h: Utwórz funkcje pomocnicze do przetwarzania ocen.Zdefiniuj funkcję
getGradeInfo, która przyjmuje wynik liczbowy (liczbę całkowitą) i zwraca obiektstd::tuplezawierający trzy wartości: ocenę literową (std::string), punkty za ocenę (double) oraz informację, czy ocena jest zaliczająca (bool). Zastosuj następującą skalę ocen:- 90+ : "A", 4.0, true
- 80-89: "B", 3.0, true
- 70-79: "C", 2.0, true
- 60-69: "D", 1.0, true
- Poniżej 60: "F", 0.0, false
Zdefiniuj również funkcję
makeScorePair, która przyjmuje nazwę kursu (std::string) i wynik (int), a następnie zwraca obiektstd::pairzawierający te wartości.main.cpp: Wczytaj cztery dane wejściowe:- Imię i nazwisko ucznia (ciąg znaków)
- Identyfikator ucznia (liczba całkowita)
- Nazwa kursu (ciąg znaków)
- Wynik (liczba całkowita)
Używaj wiązań strukturalnych w całej funkcji głównej:
- Wywołaj
createStudent, przekazując imię i nazwisko, identyfikator oraz zastępczą wartość GPA równą 0.0. Użyj wiązań strukturalnych, aby rozpakować zwróconą strukturę na poszczególne zmienne, a następnie wypisz:Student: [name] (ID: [id]) - Wywołaj
makeScorePair, przekazując nazwę kursu i wynik. Użyj wiązań strukturalnych, aby rozpakować parę, a następnie wypisz:Course: [course], Score: [score] - Wywołaj
getGradeInfo, przekazując wynik. Użyj wiązań strukturalnych, aby rozpakować wszystkie trzy elementy krotki, a następnie wypisz:(Wypisz "yes", jeśli ocena jest zaliczająca, albo "no", jeśli nie jest)Grade: [letter] Points: [points] Passing: [yes/no]
Na przykład dla danych wejściowych Alice, 1001, Math i 85:
Student: Alice (ID: 1001)
Course: Math, Score: 85
Grade: B
Points: 3
Passing: yesDla danych wejściowych Bob, 2002, Physics i 55:
Student: Bob (ID: 2002)
Course: Physics, Score: 55
Grade: F
Points: 0
Passing: noPamiętaj, aby w razie potrzeby dołączyć <tuple> i <utility>. Najważniejsze jest to, że wiązania strukturalne pozwalają rozpakować typy złożone, pary, krotki i struktury na nazwane zmienne w jednej, czytelnej deklaracji.
Spróbuj swoich sił
#include <iostream>
#include <string>
#include "Student.h"
#include "GradeUtils.h"
int main() {
// Wczytaj dane wejściowe
std::string studentName;
int studentId;
std::string courseName;
int score;
std::cin >> studentName;
std::cin >> studentId;
std::cin >> courseName;
std::cin >> score;
// TODO: Wywołaj createStudent z imieniem, identyfikatorem i tymczasową wartością GPA równą 0.0
// Użyj wiązań strukturalnych, aby rozpakować strukturę: auto [name, id, gpa] = ...
// Wypisz: Student: [name] (ID: [id])
// TODO: Wywołaj makeScorePair z nazwą kursu i wynikiem
// Użyj wiązań strukturalnych, aby rozpakować parę: auto [course, sc] = ...
// Wypisz: Course: [course], Score: [score]
// TODO: Wywołaj getGradeInfo z wynikiem
// Użyj wiązań strukturalnych, aby rozpakować krotkę: auto [letter, points, passing] = ...
// Wypisz:
// Grade: [letter]
// Points: [points]
// Zaliczenie: [yes/no] (wypisz "yes", jeśli passing ma wartość true, lub "no", jeśli ma wartość false)
return 0;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneBudowanie i kompilacja C++Pliki nagłówkowe i pliki źródłowePrzestrzenie nazw i zakresWprowadzenie do programowania obiektowego w C++Klasy a obiektyWskaźnik „this”Metody (funkcje składowe)Atrybuty (składowe danych)Podstawy konstruktorów i destruktorówPowtórzenie – prosty kalkulator4Właściwości klas
Elementy instancji a elementy statyczneGettery i setteryStałe funkcje składoweSłowo kluczowe mutableMetody i zmienne statyczneFunkcje i klasy zaprzyjaźnionePodsumowanie – menedżer konta bankowego7Dziedziczenie
Podstawy dziedziczeniaPoziomy dostępu w dziedziczeniuKolejność wywołań konstruktora i destruktoraNadpisywanie metodFunkcje wirtualne i VTableWielokrotne dziedziczenieDziedziczenie wirtualnePowtórzenie — hierarchia pracowników2Zarządzanie pamięcią
Pamięć stosu a stertyWskaźniki i referencjePamięć dynamiczna (new/delete)Inteligentne wskaźniki w C++RAII w C++Podsumowanie — menedżer tablicy dynamicznej5Hermetyzacja
Specyfikatory dostępu w C++Specyfikatory dostępu — szczegółowoUkrywanie informacjiStruktura a klasaKlasy zagnieżdżone i wewnętrznePodsumowanie — system ewidencji studentów8Polimorfizm
Polimorfizm czasu kompilacji i wykonaniaPrzeciążanie funkcjiFunkcje wirtualne — powtórkaCzysto wirtualne funkcjeKlasy abstrakcyjneProjektowanie interfejsów w C++Rzutowanie dynamiczne i RTTIPodsumowanie — kalkulator kształtów3Konstruktory i destruktory
Konstruktor domyślnyKonstruktor z parametramiKonstruktor kopiującyKonstruktor przenoszącyListy inicjalizacyjne konstruktoraKonstruktory delegująceDestruktor — szczegółowe omówienieZasada trzech / pięciu / zeraPodsumowanie — klasa String6Przeciążanie operatorów
Wprowadzenie do przeciążania operatorówPrzeciążanie operatorów arytmetycznychPrzeciążanie operatorów porównaniaOperatory strumieniowePrzeciążanie operatora przypisaniaPrzeciążanie operatorów [] i ()Operatory konwersji typówPodsumowanie — klasa Matrix9Szablony
Szablony funkcjiSzablony klasSpecjalizacja szablonówSzablony wariadycznePodstawy SFINAE i cech typówPodsumowanie — kontener generyczny12Nowoczesne funkcje C++
Semantyka przenoszenia i r-wartościDoskonałe przekazywanieWyrażenia lambda w szczegółachstd::function i std::bindconstexpr i constevalWiązania strukturalneoptional, variant, anyPoćwicz samodzielnie: Kompilator C++ online