Bankensystem
Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy. Lektion 104 von 104.
Aufgabe
EinfachErstellen wir ein Banksystem, das das Zustandsmuster, Vererbung und die Verwaltung intelligenter Zeiger demonstriert. Du erstellst ein System, in dem sich Konten in verschiedenen Zuständen (Active, Frozen, Closed) befinden können, wobei jeder Zustand ein eigenes Verhalten bei der Verarbeitung von Transaktionen aufweist.
Du organisierst deinen Code über sechs Dateien:
AccountState.h: Definiert die Infrastruktur des Zustandsmusters für Kontozustände.Erstelle eine abstrakte Basisklasse
AccountStatemit rein virtuellen Methoden:deposit(double amount): gibt true zurück, wenn eine Einzahlung zulässig ist, andernfalls falsewithdraw(double amount): gibt true zurück, wenn eine Auszahlung zulässig ist, andernfalls falsegetStateName(): gibt den Namen des Zustands als Zeichenkette zurück
Implementiere drei konkrete Zustände:
ActiveState: Erlaubt sowohl Einzahlungen als auch Auszahlungen und gibt"Active"zurückFrozenState: Erlaubt Einzahlungen, lehnt aber Auszahlungen ab und gibt"Frozen"zurückClosedState: Lehnt sowohl Einzahlungen als auch Auszahlungen ab und gibt"Closed"zurück
Account.h: Erstellt eine Kontohierarchie mit Zustandsverwaltung.Erstelle eine Basisklasse
Accountmit:- Kontonummer (Zeichenkette), Name des Kontoinhabers und Kontostand
- Einem
std::unique_ptr<AccountState>zur Verwaltung des aktuellen Zustands deposit(double amount): Prüft zuerst den Zustand; wenn die Einzahlung zulässig ist, wird der Betrag zum Kontostand addiert und"Deposited [amount] to [accountNumber]"ausgegeben, andernfalls"Deposit rejected: account is [stateName]"withdraw(double amount): Prüft den Zustand; wenn die Auszahlung zulässig ist und ausreichende Mittel vorhanden sind, wird der Betrag abgezogen und"Withdrew [amount] from [accountNumber]"ausgegeben. Wenn der Zustand die Auszahlung ablehnt, wird"Withdrawal rejected: account is [stateName]"ausgegeben. Wenn die Mittel nicht ausreichen, wird"Insufficient funds"ausgegebenfreeze(),activate()undclose(): Ändern den KontozustandgetInfo(): Gibt"[accountNumber] ([ownerName]): $[balance] - [stateName]"zurück- Virtuelles
getAccountType(), das"Basic"zurückgibt
Erstelle zwei abgeleitete Kontotypen:
SavingsAccount: Besitzt eine Mindestguthabenanforderung, die an den Konstruktor übergeben wird. Überschreibe withdraw, sodass zusätzlich geprüft wird, ob die Auszahlung den Kontostand unter das Mindestguthaben senken würde. Falls dies der Fall ist, gib"Cannot go below minimum balance of [minimum]"aus. Gibt"Savings"als Kontotyp zurück.CheckingAccount: Besitzt ein Überziehungslimit, das an den Konstruktor übergeben wird. Erlaubt Auszahlungen bis zur Höhe von (Kontostand + overdraftLimit). Gibt"Checking"als Kontotyp zurück.
Transaction.h: Modelliert Transaktionen als Objekte.Erstelle eine Klasse
Transaction, die Folgendes erfasst:- Transaktionstyp (Zeichenkette: "Deposit", "Withdrawal", "Transfer")
- Betrag
- Beteiligte Kontonummer
- Erfolgsstatus (bool)
Füge eine Methode
getDescription()hinzu, die"[type]: $[amount] on [accountNumber] - [Success/Failed]"zurückgibtCustomer.h: Erstellt einen Kunden, der mehrere Konten besitzt.Ein
Customerbesitzt einen Namen, eine ID und einen Vektor ausstd::shared_ptr<Account>. Implementiere:addAccount(std::shared_ptr<Account> account)getAccount(const std::string& accountNumber): Gibt das passende Konto oder nullptr zurückgetTotalBalance(): Summiert die Kontostände aller KontenlistAccounts(): Gibt die Informationen zu jedem Konto aus
Bank.h: Koordiniert die Bankgeschäfte.Die Klasse
Bankspeichert Kunden und verwaltet eine Transaktionshistorie. Implementiere:addCustomer(std::shared_ptr<Customer> customer)findAccount(const std::string& accountNumber): Durchsucht alle Kunden nach dem KontoprocessDeposit(const std::string& accountNumber, double amount): Findet das Konto, führt die Einzahlung durch und erfasst die TransaktionprocessWithdrawal(const std::string& accountNumber, double amount): Findet das Konto, führt die Auszahlung durch und erfasst die TransaktiongetTransactionCount(): Gibt die Gesamtzahl der verarbeiteten Transaktionen zurück
main.cpp: Demonstriert dein Banksystem.Lies vier Eingaben ein:
- Kundendaten (Format:
name,customerId) - Daten des Sparkontos (Format:
accountNumber,minBalance) - Operation 1 (Format:
action,accountNumber,amount, wobei actiondepositoderwithdrawist) - Operation 2 (Format:
action,accountNumber,amountoderfreeze,accountNumber)
Erstelle die Bank und den Kunden. Erstelle ein Sparkonto mit dem Kunden als Inhaber und füge es dem Kunden hinzu. Füge den Kunden zur Bank hinzu. Verarbeite beide Operationen (wenn es sich um einen freeze-Befehl handelt, friere das Konto ein und versuche anschließend eine kleine Auszahlung von $10, um den Zustand zu demonstrieren). Gib schließlich die Kontoliste des Kunden und die Gesamtzahl der Transaktionen als
"Transactions: [count]"aus.- Kundendaten (Format:
Zum Beispiel mit den Eingaben Alice,C001, SAV001,100, deposit,SAV001,500 und withdraw,SAV001,200:
Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2Mit den Eingaben Bob,C002, SAV002,50, deposit,SAV002,100 und freeze,SAV002:
Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2Mit den Eingaben Carol,C003, SAV003,200, deposit,SAV003,250 und withdraw,SAV003,100:
Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2Diese Herausforderung verbindet das Zustandsmuster zur Verwaltung des Kontoverhaltens, Vererbung für verschiedene Kontotypen, intelligente Zeiger für Besitzverhältnisse und die Nachverfolgung von Transaktionen – alles zentrale Konzepte, die du im Laufe dieses Kurses gemeistert hast.
Probier es selbst
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"
int main() {
// Eingabe 1 lesen: Kundendetails (Format: name,customerId)
std::string customerInput;
std::getline(std::cin, customerInput);
// Eingabe 2 lesen: Sparkontodetails (Format: accountNumber,minBalance)
std::string accountInput;
std::getline(std::cin, accountInput);
// Eingabe 3 lesen: Operation 1 (Format: action,accountNumber,amount)
std::string op1Input;
std::getline(std::cin, op1Input);
// Eingabe 4 lesen: Operation 2 (Format: action,accountNumber,amount oder freeze,accountNumber)
std::string op2Input;
std::getline(std::cin, op2Input);
// TODO: Kundendetails aus customerInput parsen
// Hinweis: Verwende find(',') um den String zu teilen
// TODO: Kontodetails aus accountInput parsen
// TODO: Die Bank erstellen
// TODO: Den Kunden erstellen
// TODO: Ein Sparkonto mit dem Kunden als Inhaber erstellen
// TODO: Das Konto zum Kunden hinzufügen
// TODO: Den Kunden zur Bank hinzufügen
// TODO: Operation 1 parsen und verarbeiten
// Format: action,accountNumber,amount (action ist "deposit" oder "withdraw")
// TODO: Operation 2 parsen und verarbeiten
// Könnte sein: action,accountNumber,amount ODER freeze,accountNumber
// Bei freeze das Konto einfrieren und dann eine Abhebung von $10 versuchen
// TODO: Kontoliste des Kunden ausgeben
// TODO: Print transaction count as "Transactions: [count]"
return 0;
}
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 ContainerÜbe selbstständig: Online-C++-Compiler