一, 银行账户管理系统拓展
项目概述
对之前的银行账户管理系统进行拓展,增加如下功能:
- 账户类型:支持不同类型的账户,比如储蓄账户和支票账户。
- 利息功能:为储蓄账户添加计算利息的功能。
- 透支保护:为支票账户添加透支保护功能。
- 账户列表:管理多个账户。
代码实现
#include <iostream>
#include <string>
#include <vector>
class BankAccount {
protected:
std::string accountNumber;
std::string accountHolder;
double balance;
public:
BankAccount(std::string number, std::string holder)
: accountNumber(number), accountHolder(holder), balance(0.0) {}
virtual void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
virtual void withdraw(double amount) {
if (amount > 0 && balance >= amount) {
balance -= amount;
}
}
virtual void displayAccount() const{
std::cout << "Account Number: " << accountNumber << "\n"
<< "Account Holder: " << accountHolder << "\n"
<<"Balance: " << balance << "\n";
}
virtual void addInterest() {}
};
class SavingsAccount : public BankAccount {
private:
double interestRate;
public:
SavingsAccount(std::string number, std::string holder, double rate)
: BankAccount(number, holder), interestRate(rate) {}
void addInterest() override {
double interest = balance * interestRate / 100;
deposit(interest);
}
};
class CheckingAccount : public BankAccount {
private:
double overdraftLimit;
public:
CheckingAccount(std::string number, std::string holder, double limit)
: BankAccount(number, holder), overdraftLimit(limit) {}
void withdraw(double amount) override {
if (amount > 0 && balance - amount >= - overdraftLimit) {
balance -= amount;
}
}
};
int main() {
std::vector<BankAccount*> accounts;
accounts.push_back(new SavingsAccount("123445678", "张三", 3));
accounts.push_back(new CheckingAccount("87654321", "里斯", 500));
accounts[0]->deposit(1000);
accounts[0]->addInterest();
accounts[1]->deposit(500);
accounts[1]->withdraw(1000);
for (BankAccount* account : accounts) {
account->displayAccount();
}
for (BankAccount* account : accounts) {
delete account;
}
return 0;
}
项目解析
- 类的继承和多态:
SavingsAccount
和CheckingAccount
继承自BankAccount
类,并重写了一些方法来实现特定的功能。 - 虚函数:
addInterest
和withdraw
是虚函数,允许在派生类中被重写以实现不同的行为。 - 账户类型:通过继承和多态,支持不同类型的账户。
- 利息计算:
SavingsAccount
类中的addInterest
方法用于计算利息。 - 透支保护:
CheckingAccount
类重写了withdraw
方法,以提供透支保护。 - 管理多账户:使用
std::vector<BankAccount*>
来存储和管理不同的账户。 - 资源管理:使用
new
在堆上创建对象,并在最后使用delete
释放内存。
部分代码片段解释
1.protected
在C++中,`protected` 关键字是一个访问修饰符,用于控制对类成员的访问权限。`protected` 修饰符在继承关系中起着特殊作用:
1. **对于类本身和友元类**:`protected` 成员就像 `private` 成员一样,只能被类本身的成员函数、类的构造函数、析构函数、友元类的成员函数访问。
2. **对于派生类**:`protected` 成员可以被派生类(子类)访问。这是与 `private` 的主要区别。使用 `protected` 修饰符允许子类访问和修改这些成员,同时仍然隐藏这些成员不被类的外部访问。
在我们之前的银行账户管理系统例子中,`BankAccount` 类中的 `accountNumber`、`accountHolder` 和 `balance` 成员被声明为 `protected`。这意味着这些成员可以在 `BankAccount` 类及其派生类(如 `SavingsAccount` 和 `CheckingAccount`)中被直接访问和修改,但对于其他类则是不可见的。
使用 `protected` 而非 `private` 是面向对象设计中的一个常见做法,它在保持封装性的同时,又提供了一定的灵活性,使得派生类能够更方便地使用和扩展基类的功能。、
2.virtual
在C++中,`virtual` 关键字用于声明函数为“虚函数”。这对实现多态性,即在继承体系中的不同类对象能表现出不同行为,至关重要。在基类中声明一个函数为 `virtual` 意味着派生类可以重写该函数,以提供特定于派生类的行为。
1, 作用
- **允许在派生类中重写**:如果在基类中有一个 `virtual` 函数,派生类可以重写该函数以实现不同的功能。
- **动态绑定**:当使用基类的指针或引用调用虚函数时,将会根据对象的实际类型来调用相应的函数版本。这种行为在运行时确定,因此称为动态绑定。
2. 示例
在之前的银行账户例子中,`virtual void addInterest()` 函数在 `BankAccount` 类中被声明为虚函数。这意味着我们可以在任何继承自 `BankAccount` 的子类中重写 `addInterest` 函数。
在 `SavingsAccount` 类中,我们重写了 `addInterest` 函数,以实现特定于储蓄账户的利息计算逻辑。这样,当我们调用 `addInterest` 函数时,如果对象是 `SavingsAccount` 类型的实例,那么将调用 `SavingsAccount` 中重写的 `addInterest` 函数。如果对象是 `BankAccount` 类型或其他未重写 `addInterest` 函数的派生类的实例,将调用 `BankAccount` 类中的 `addInterest` 函数。
3. 重要点
- 声明为 `virtual` 的函数通常有一个在基类中的默认实现,但它们主要是为了在派生类中被重写。
- 如果在派生类中重写虚函数,最好使用 `override` 关键字明确表示。这增加了代码的可读性,并帮助编译器检查重写的正确性。
- 在析构函数中使用 `virtual` 是多态类层次结构中的一个重要和常见做法,以确保通过基类指针删除派生类对象时,能够调用正确的析构函数。
3. main()函数
1. 创建账户对象
std::vector<BankAccount*> accounts;
:定义了一个BankAccount
指针的向量(动态数组)。accounts.push_back(new SavingsAccount("123445678", "张三", 3));
:创建一个SavingsAccount
对象,并将其地址存入accounts
向量。这里"123445678"
是账户号码,"张三"
是账户持有人,3
是利率。accounts.push_back(new CheckingAccount("87654321", "里斯", 500));
:类似地,创建一个CheckingAccount
对象。
2. 操作账户
- 使用指针访问运算符
->
来调用BankAccount
对象的方法。 - 对第一个账户(储蓄账户)进行存款和计算利息。
- 对第二个账户(支票账户)进行存款和取款。
3. 显示账户信息
遍历 accounts
向量中的每个账户,调用它们的 displayAccount
方法来显示信息。
4. 清理资源
- 这个循环遍历
accounts
向量,并释放每个账户对象占用的堆内存。 - 在C++中,使用
new
分配的内存必须显式地使用delete
释放,以防内存泄漏。