Sistema bancario
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 104 di 104.
Sfida
FacileCostruiamo un sistema bancario che dimostri il pattern State, l'ereditarietà e la gestione con puntatori intelligenti. Creerai un sistema in cui i conti possono trovarsi in stati diversi (Active, Frozen, Closed), ciascuno con comportamenti distinti per la gestione delle transazioni.
Organizzerai il codice in sei file:
AccountState.h: definisci l'infrastruttura del pattern State per gli stati dei conti.Crea una classe base astratta
AccountStatecon metodi virtuali puri:deposit(double amount): restituisce true se il deposito è consentito, false altrimentiwithdraw(double amount): restituisce true se il prelievo è consentito, false altrimentigetStateName(): restituisce il nome dello stato come stringa
Implementa tre stati concreti:
ActiveState: consente sia i depositi sia i prelievi, restituisce"Active"FrozenState: consente i depositi ma rifiuta i prelievi, restituisce"Frozen"ClosedState: rifiuta sia i depositi sia i prelievi, restituisce"Closed"
Account.h: crea una gerarchia di conti con gestione degli stati.Crea una classe base
Accountcon:- Numero del conto (stringa), nome del titolare e saldo
- Un
std::unique_ptr<AccountState>per gestire lo stato corrente deposit(double amount): verifica prima lo stato; se il deposito è consentito, aggiunge l'importo al saldo e stampa"Deposited [amount] to [accountNumber]", altrimenti stampa"Deposit rejected: account is [stateName]"withdraw(double amount): verifica lo stato; se il prelievo è consentito e i fondi sono sufficienti, detrae l'importo e stampa"Withdrew [amount] from [accountNumber]". Se lo stato rifiuta il prelievo, stampa"Withdrawal rejected: account is [stateName]". Se i fondi sono insufficienti, stampa"Insufficient funds"freeze(),activate()eclose(): cambiano lo stato del contogetInfo(): restituisce"[accountNumber] ([ownerName]): $[balance] - [stateName]"getAccountType()virtuale che restituisce"Basic"
Crea due tipi di conto derivati:
SavingsAccount: prevede un saldo minimo (passato al costruttore). Sovrascrivi withdraw per verificare anche se il prelievo farebbe scendere il saldo sotto il minimo; in tal caso, stampa"Cannot go below minimum balance of [minimum]". Restituisce"Savings"come tipo di conto.CheckingAccount: prevede un limite di scoperto (passato al costruttore). Consente prelievi fino a (saldo + overdraftLimit). Restituisce"Checking"come tipo di conto.
Transaction.h: modella le transazioni come oggetti.Crea una classe
Transactionche registri:- Tipo di transazione (stringa: "Deposit", "Withdrawal", "Transfer")
- Importo
- Numero del conto coinvolto
- Esito (bool)
Aggiungi un metodo
getDescription()che restituisca"[type]: $[amount] on [accountNumber] - [Success/Failed]"Customer.h: crea un cliente che possiede più conti.Un
Customerha un nome, un ID e un vector distd::shared_ptr<Account>. Implementa:addAccount(std::shared_ptr<Account> account)getAccount(const std::string& accountNumber): restituisce il conto corrispondente oppure nullptrgetTotalBalance(): somma i saldi di tutti i contilistAccounts(): stampa le informazioni di ciascun conto
Bank.h: coordina le operazioni bancarie.La classe
Bankmemorizza i clienti e mantiene uno storico delle transazioni. Implementa:addCustomer(std::shared_ptr<Customer> customer)findAccount(const std::string& accountNumber): cerca il conto tra tutti i clientiprocessDeposit(const std::string& accountNumber, double amount): trova il conto, effettua il deposito e registra la transazioneprocessWithdrawal(const std::string& accountNumber, double amount): trova il conto, effettua il prelievo e registra la transazionegetTransactionCount(): restituisce il totale delle transazioni elaborate
main.cpp: mostra il funzionamento del sistema bancario.Leggi quattro input:
- Dati del cliente (formato:
name,customerId) - Dati del conto di risparmio (formato:
accountNumber,minBalance) - Operazione 1 (formato:
action,accountNumber,amount, dove action èdepositoppurewithdraw) - Operazione 2 (formato:
action,accountNumber,amountoppurefreeze,accountNumber)
Crea la banca e il cliente. Crea un conto di risparmio intestato al cliente e aggiungilo al cliente. Aggiungi il cliente alla banca. Esegui entrambe le operazioni (se è un comando freeze, congela il conto e poi prova un piccolo prelievo di $10 per mostrare lo stato). Infine, stampa l'elenco dei conti del cliente e il numero totale di transazioni nel formato
"Transactions: [count]".- Dati del cliente (formato:
Per esempio, con gli input Alice,C001, SAV001,100, deposit,SAV001,500 e withdraw,SAV001,200:
Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2Con gli input Bob,C002, SAV002,50, deposit,SAV002,100 e freeze,SAV002:
Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2Con gli input Carol,C003, SAV003,200, deposit,SAV003,250 e withdraw,SAV003,100:
Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2Questa sfida riunisce il pattern State per gestire i comportamenti dei conti, l'ereditarietà per i diversi tipi di conto, i puntatori intelligenti per le relazioni di proprietà e il tracciamento delle transazioni: tutti concetti fondamentali che hai imparato durante questo corso.
Provalo tu
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"
int main() {
// Leggi l'input 1: dati del cliente (formato: name,customerId)
std::string customerInput;
std::getline(std::cin, customerInput);
// Leggi l'input 2: dati del conto di risparmio (formato: accountNumber,minBalance)
std::string accountInput;
std::getline(std::cin, accountInput);
// Leggi l'input 3: operazione 1 (formato: action,accountNumber,amount)
std::string op1Input;
std::getline(std::cin, op1Input);
// Leggi l'input 4: operazione 2 (formato: action,accountNumber,amount oppure freeze,accountNumber)
std::string op2Input;
std::getline(std::cin, op2Input);
// TODO: Estrai i dati del cliente da customerInput
// Suggerimento: usa find(',') per suddividere la stringa
// TODO: Estrai i dati del conto da accountInput
// TODO: Crea la banca
// TODO: Crea il cliente
// TODO: Crea un conto di risparmio intestato al cliente
// TODO: Aggiungi il conto al cliente
// TODO: Aggiungi il cliente alla banca
// TODO: Analizza ed esegui l'operazione 1
// Formato: action,accountNumber,amount (action è "deposit" o "withdraw")
// TODO: Analizza ed esegui l'operazione 2
// Può essere: action,accountNumber,amount oppure freeze,accountNumber
// Se l'azione è freeze, blocca il conto e poi prova a prelevare $10
// TODO: Stampa l'elenco dei conti del cliente
// TODO: Stampa il numero di transazioni nel formato "Transactions: [count]"
return 0;
}
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