银行系统
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 104 课,共 104 课。
挑战
简单让我们构建一个银行系统,用来演示状态模式、继承和智能指针管理。你将创建一个系统,其中的账户可以处于不同状态(Active、Frozen、Closed),每种状态在处理交易时都有不同的行为。
你将把代码分成六个文件:
AccountState.h:定义账户状态所需的状态模式基础结构。创建一个抽象的
AccountState基类,包含以下纯虚方法:deposit(double amount):如果允许存款,则返回 true,否则返回 falsewithdraw(double amount):如果允许取款,则返回 true,否则返回 falsegetStateName():以字符串形式返回状态名称
实现三个具体状态:
ActiveState:允许存款和取款,返回"Active"FrozenState:允许存款但拒绝取款,返回"Frozen"ClosedState:拒绝存款和取款,返回"Closed"
Account.h:构建带有状态管理功能的账户继承体系。创建一个
Account基类,包含:- 账户号码(字符串)、账户持有人姓名和余额
- 一个用于管理当前状态的
std::unique_ptr<AccountState> deposit(double amount):先检查状态;如果允许,则将金额加到余额中并打印"Deposited [amount] to [accountNumber]",否则打印"Deposit rejected: account is [stateName]"withdraw(double amount):检查状态;如果允许且资金充足,则扣除金额并打印"Withdrew [amount] from [accountNumber]"。如果状态拒绝取款,则打印"Withdrawal rejected: account is [stateName]"。如果资金不足,则打印"Insufficient funds"freeze()、activate()和close():更改账户状态getInfo():返回"[accountNumber] ([ownerName]): $[balance] - [stateName]"- 虚方法
getAccountType(),返回"Basic"
创建两种派生账户类型:
SavingsAccount:有最低余额要求(通过构造函数传入)。重写 withdraw,同时检查取款是否会导致余额低于最低余额;如果会,则打印"Cannot go below minimum balance of [minimum]"。账户类型返回"Savings"。CheckingAccount:有透支额度(通过构造函数传入)。允许取款金额不超过(余额 + overdraftLimit)。账户类型返回"Checking"。
Transaction.h:将交易建模为对象。创建一个
Transaction类,记录以下信息:- 交易类型(字符串:"Deposit"、"Withdrawal"、"Transfer")
- 金额
- 涉及的账户号码
- 成功状态(bool)
添加一个
getDescription()方法,返回"[type]: $[amount] on [accountNumber] - [Success/Failed]"Customer.h:创建拥有多个账户的客户。Customer有姓名、ID,以及一个由std::shared_ptr<Account>组成的 vector。实现以下方法:addAccount(std::shared_ptr<Account> account)getAccount(const std::string& accountNumber):返回匹配的账户,否则返回 nullptrgetTotalBalance():计算所有账户的余额总和listAccounts():打印每个账户的信息
Bank.h:协调银行业务。Bank类保存客户信息并维护交易历史记录。实现以下方法:addCustomer(std::shared_ptr<Customer> customer)findAccount(const std::string& accountNumber):在所有客户中搜索该账户processDeposit(const std::string& accountNumber, double amount):查找账户,执行存款,并记录交易processWithdrawal(const std::string& accountNumber, double amount):查找账户,执行取款,并记录交易getTransactionCount():返回已处理的交易总数
main.cpp:演示你的银行系统。读取四个输入:
- 客户信息(格式:
name,customerId) - 储蓄账户信息(格式:
accountNumber,minBalance) - 操作 1(格式:
action,accountNumber,amount,其中 action 是deposit或withdraw) - 操作 2(格式:
action,accountNumber,amount或freeze,accountNumber)
创建银行和客户。创建一个以该客户为账户持有人的储蓄账户,并将它添加到客户。将客户添加到银行。处理两项操作(如果是冻结命令,则冻结账户,然后尝试取款 10 美元,以演示该状态)。最后,打印客户的账户列表,并按
"Transactions: [count]"的格式打印交易总数。- 客户信息(格式:
例如,输入为 Alice,C001、SAV001,100、deposit,SAV001,500 和 withdraw,SAV001,200 时:
Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2输入为 Bob,C002、SAV002,50、deposit,SAV002,100 和 freeze,SAV002 时:
Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2输入为 Carol,C003、SAV003,200、deposit,SAV003,250 和 withdraw,SAV003,100 时:
Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2这个挑战综合运用了状态模式来管理账户行为、继承来实现不同账户类型、智能指针来管理所有权关系,以及交易跟踪。这些都是你在本课程中掌握的核心概念。
亲手试试
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"
int main() {
// 读取输入 1:客户信息(格式:name,customerId)
std::string customerInput;
std::getline(std::cin, customerInput);
// 读取输入 2:储蓄账户信息(格式:accountNumber,minBalance)
std::string accountInput;
std::getline(std::cin, accountInput);
// 读取输入 3:操作 1(格式:action,accountNumber,amount)
std::string op1Input;
std::getline(std::cin, op1Input);
// 读取输入 4:操作 2(格式:action,accountNumber,amount 或 freeze,accountNumber)
std::string op2Input;
std::getline(std::cin, op2Input);
// TODO:从 customerInput 解析客户信息
// 提示:用 find(',') 拆分字符串
// TODO:从 accountInput 解析账户信息
// TODO:创建银行
// TODO:创建客户
// TODO:创建一个以该客户为所有者的储蓄账户
// TODO:将账户添加到客户名下
// TODO:将客户添加到银行
// TODO: 解析并处理操作 1
// 格式:action,accountNumber,amount(action 为 "deposit" 或 "withdraw")
// TODO: 解析并处理操作 2
// 可能是:action,accountNumber,amount 或 freeze,accountNumber
// 如果是 freeze,先冻结账户,再尝试取出 $10
// TODO: 输出客户的账户列表
// TODO: 按 "Transactions: [count]" 的格式输出交易次数
return 0;
}
面向对象编程中的所有课
自己练习: C++ 在线编译器