Sistema bancario
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 104 de 104.
Desafío
FácilConstruyamos un sistema bancario que demuestre el patrón State, la herencia y la gestión de punteros inteligentes. Crearás un sistema en el que las cuentas pueden estar en distintos estados (Active, Frozen, Closed), cada uno con comportamientos diferentes para gestionar las transacciones.
Organizarás tu código en seis archivos:
AccountState.h: Define la infraestructura del patrón State para los estados de las cuentas.Crea una clase base abstracta
AccountStatecon métodos virtuales puros:deposit(double amount): devuelve true si se permite el depósito y false en caso contrariowithdraw(double amount): devuelve true si se permite el retiro y false en caso contrariogetStateName(): devuelve el nombre del estado como una cadena
Implementa tres estados concretos:
ActiveState: permite tanto depósitos como retiros y devuelve"Active"FrozenState: permite depósitos, pero rechaza retiros, y devuelve"Frozen"ClosedState: rechaza tanto depósitos como retiros y devuelve"Closed"
Account.h: Construye una jerarquía de cuentas con gestión de estados.Crea una clase base
Accountcon:- Número de cuenta (cadena), nombre del titular y saldo
- Un
std::unique_ptr<AccountState>para gestionar el estado actual deposit(double amount): comprueba primero el estado; si se permite, suma el importe al saldo e imprime"Deposited [amount] to [accountNumber]"; de lo contrario, imprime"Deposit rejected: account is [stateName]"withdraw(double amount): comprueba el estado; si se permite y hay fondos suficientes, descuenta el importe e imprime"Withdrew [amount] from [accountNumber]". Si el estado lo rechaza, imprime"Withdrawal rejected: account is [stateName]". Si no hay fondos suficientes, imprime"Insufficient funds"freeze(),activate()yclose(): cambian el estado de la cuentagetInfo(): devuelve"[accountNumber] ([ownerName]): $[balance] - [stateName]"getAccountType()virtual que devuelve"Basic"
Crea dos tipos de cuenta derivados:
SavingsAccount: tiene un requisito de saldo mínimo (que se pasa al constructor). Sobrescribe withdraw para comprobar también si el retiro haría que el saldo quedara por debajo del mínimo; si es así, imprime"Cannot go below minimum balance of [minimum]". Devuelve"Savings"como tipo de cuenta.CheckingAccount: tiene un límite de sobregiro (que se pasa al constructor). Permite retiros de hasta (saldo + overdraftLimit). Devuelve"Checking"como tipo de cuenta.
Transaction.h: Modela las transacciones como objetos.Crea una clase
Transactionque registre:- Tipo de transacción (cadena: "Deposit", "Withdrawal", "Transfer")
- Importe
- Número de cuenta involucrado
- Estado de éxito (bool)
Añade un método
getDescription()que devuelva"[type]: $[amount] on [accountNumber] - [Success/Failed]"Customer.h: Crea un cliente que sea propietario de varias cuentas.Un
Customertiene un nombre, un ID y un vector destd::shared_ptr<Account>. Implementa:addAccount(std::shared_ptr<Account> account)getAccount(const std::string& accountNumber): devuelve la cuenta coincidente o nullptrgetTotalBalance(): suma los saldos de todas las cuentaslistAccounts(): imprime la información de cada cuenta
Bank.h: Coordina las operaciones bancarias.La clase
Bankalmacena clientes y mantiene un historial de transacciones. Implementa:addCustomer(std::shared_ptr<Customer> customer)findAccount(const std::string& accountNumber): busca la cuenta entre todos los clientesprocessDeposit(const std::string& accountNumber, double amount): encuentra la cuenta, realiza el depósito y registra la transacciónprocessWithdrawal(const std::string& accountNumber, double amount): encuentra la cuenta, realiza el retiro y registra la transaccióngetTransactionCount(): devuelve el total de transacciones procesadas
main.cpp: Demuestra tu sistema bancario.Lee cuatro entradas:
- Datos del cliente (formato:
name,customerId) - Datos de la cuenta de ahorros (formato:
accountNumber,minBalance) - Operación 1 (formato:
action,accountNumber,amount, donde action esdepositowithdraw) - Operación 2 (formato:
action,accountNumber,amountofreeze,accountNumber)
Crea el banco y el cliente. Crea una cuenta de ahorros cuyo titular sea el cliente y añádela al cliente. Añade el cliente al banco. Procesa ambas operaciones (si es un comando freeze, congela la cuenta y luego intenta realizar un pequeño retiro de $10 para demostrar el estado). Finalmente, imprime la lista de cuentas del cliente y el número total de transacciones como
"Transactions: [count]".- Datos del cliente (formato:
Por ejemplo, con las entradas Alice,C001, SAV001,100, deposit,SAV001,500 y withdraw,SAV001,200:
Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2Con las entradas Bob,C002, SAV002,50, deposit,SAV002,100 y freeze,SAV002:
Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2Con las entradas Carol,C003, SAV003,200, deposit,SAV003,250 y withdraw,SAV003,100:
Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2Este desafío reúne el patrón State para gestionar los comportamientos de las cuentas, la herencia para los distintos tipos de cuenta, los punteros inteligentes para las relaciones de propiedad y el seguimiento de transacciones: todos son conceptos fundamentales que has dominado a lo largo de este curso.
Pruébalo tú mismo
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"
int main() {
// Leer entrada 1: Detalles del cliente (formato: name,customerId)
std::string customerInput;
std::getline(std::cin, customerInput);
// Leer entrada 2: Detalles de la cuenta de ahorros (formato: accountNumber,minBalance)
std::string accountInput;
std::getline(std::cin, accountInput);
// Leer entrada 3: Operación 1 (formato: action,accountNumber,amount)
std::string op1Input;
std::getline(std::cin, op1Input);
// Leer entrada 4: Operación 2 (formato: action,accountNumber,amount o freeze,accountNumber)
std::string op2Input;
std::getline(std::cin, op2Input);
// TODO: Analiza los detalles del cliente desde customerInput
// Pista: Usa find(',') para dividir la cadena
// TODO: Analiza los detalles de la cuenta desde accountInput
// TODO: Crea el banco
// TODO: Crea el cliente
// TODO: Crea una cuenta de ahorros con el cliente como propietario
// TODO: Añade la cuenta al cliente
// TODO: Añade el cliente al banco
// TODO: Analiza y procesa la operación 1
// Formato: action,accountNumber,amount (action es "deposit" o "withdraw")
// TODO: Analiza y procesa la operación 2
// Podría ser: action,accountNumber,amount O freeze,accountNumber
// Si freeze, congela la cuenta y luego intenta un retiro de $10
// TODO: Imprime la lista de cuentas del cliente
// TODO: Print transaction count as "Transactions: [count]"
return 0;
}
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genéricoPractica por tu cuenta: Compilador de C++ online