当前位置:

首页 > 编程开发 > C++简易银行系统类与对象教程

C++简易银行系统类与对象教程

如何利用C++的类与对象模拟银行账户的基本操作并构建管理系统?1.定义BankAccount类,包含账户ID、持有人姓名和余额等属性,并实现存款、取款、查询余额及打印账户信息的方法;2.创建Bank类,使用std::vector容器管理多个BankAccount对象,提供添加、删除、查找账户等功能;3.为处理并发访问,引入std::mutex互斥锁保护balance变量,确保线程安全;4.扩展支持不同账户类型时,使用继承机制设计SavingsAccount(储蓄账户)和CheckingAccount(支票

如何利用C++的类与对象模拟银行账户的基本操作并构建管理系统?1. 定义BankAccount类,包含账户ID、持有人姓名和余额等属性,并实现存款、取款、查询余额及打印账户信息的方法;2. 创建Bank类,使用std::vector容器管理多个BankAccount对象,提供添加、删除、查找账户等功能;3. 为处理并发访问,引入std::mutex互斥锁保护balance变量,确保线程安全;4. 扩展支持不同账户类型时,使用继承机制设计SavingsAccount(储蓄账户)和CheckingAccount(支票账户),分别实现利率计算和透支功能;5. 实现账户数据持久化,可通过文件存储使用ofstream和ifstream进行读写操作,或通过数据库如SQLite实现更复杂的数据管理。

怎样用C++制作简易银行账户系统 类与对象的基础应用

核心在于如何利用C++的类与对象,模拟银行账户的创建、存取款等基本操作,构建一个简单的银行账户管理系统。

怎样用C++制作简易银行账户系统 类与对象的基础应用

解决方案:

首先,我们需要定义一个BankAccount类,它将包含账户的基本属性,如账户ID、账户持有人姓名和账户余额,以及相关的操作方法。

怎样用C++制作简易银行账户系统 类与对象的基础应用
#include 
#include 

class BankAccount {
private:
    int accountID;
    std::string accountHolderName;
    double balance;

public:
    // 构造函数
    BankAccount(int id, std::string name, double initialBalance) : accountID(id), accountHolderName(name), balance(initialBalance) {}

    // 获取账户ID
    int getAccountID() const {
        return accountID;
    }

    // 获取账户持有人姓名
    std::string getAccountHolderName() const {
        return accountHolderName;
    }

    // 获取账户余额
    double getBalance() const {
        return balance;
    }

    // 存款
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            std::cout << "存款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "存款金额必须大于0" << std::endl;
        }
    }

    // 取款
    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            std::cout << "取款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "取款失败,余额不足或取款金额无效" << std::endl;
        }
    }

    // 打印账户信息
    void printAccountInfo() const {
        std::cout << "账户ID: " << accountID << std::endl;
        std::cout << "账户持有人姓名: " << accountHolderName << std::endl;
        std::cout << "账户余额: " << balance << std::endl;
    }
};

int main() {
    // 创建一个银行账户对象
    BankAccount account1(12345, "张三", 1000.0);

    // 打印账户信息
    account1.printAccountInfo();

    // 存款
    account1.deposit(500.0);

    // 取款
    account1.withdraw(200.0);

    // 再次打印账户信息
    account1.printAccountInfo();

    return 0;
}

这个简单的例子展示了如何创建一个BankAccount类,并实现存款和取款功能。 接下来,可以考虑如何扩展这个系统,例如添加账户管理功能,允许多个账户存在。

如何添加账户管理功能,实现多个账户的管理?

怎样用C++制作简易银行账户系统 类与对象的基础应用

创建一个Bank类,该类包含一个BankAccount对象的容器(例如std::vector),并提供添加账户、删除账户、查找账户等功能。

#include 
#include 
#include 

// BankAccount 类 (如上所示)

class Bank {
private:
    std::vector accounts;

public:
    // 添加账户
    void addAccount(const BankAccount& account) {
        accounts.push_back(account);
        std::cout << "账户已添加" << std::endl;
    }

    // 删除账户 (根据账户ID)
    void removeAccount(int accountID) {
        for (auto it = accounts.begin(); it != accounts.end(); ++it) {
            if (it->getAccountID() == accountID) {
                accounts.erase(it);
                std::cout << "账户已删除" << std::endl;
                return;
            }
        }
        std::cout << "未找到该账户" << std::endl;
    }

    // 查找账户 (根据账户ID)
    BankAccount* findAccount(int accountID) {
        for (auto& account : accounts) {
            if (account.getAccountID() == accountID) {
                return &account;
            }
        }
        std::cout << "未找到该账户" << std::endl;
        return nullptr;
    }

    // 打印所有账户信息
    void printAllAccounts() const {
        if (accounts.empty()) {
            std::cout << "银行中没有账户" << std::endl;
            return;
        }
        for (const auto& account : accounts) {
            account.printAccountInfo();
            std::cout << "---------------------" << std::endl;
        }
    }
};

int main() {
    Bank myBank;

    // 创建账户
    BankAccount account1(12345, "张三", 1000.0);
    BankAccount account2(67890, "李四", 500.0);

    // 添加账户到银行
    myBank.addAccount(account1);
    myBank.addAccount(account2);

    // 打印所有账户信息
    myBank.printAllAccounts();

    // 查找账户
    BankAccount* foundAccount = myBank.findAccount(12345);
    if (foundAccount != nullptr) {
        std::cout << "找到账户:" << foundAccount->getAccountHolderName() << std::endl;
    }

    // 删除账户
    myBank.removeAccount(67890);

    // 再次打印所有账户信息
    myBank.printAllAccounts();

    return 0;
}

这个Bank类维护了一个BankAccount的容器,并提供了添加、删除和查找账户的功能。 值得注意的是,错误处理和边界情况的处理非常重要,例如,当尝试删除或查找不存在的账户时,应该给出明确的提示。

如何处理并发访问银行账户时的线程安全问题?

当多个线程同时访问和修改银行账户余额时,可能会出现数据竞争,导致账户余额错误。 为了解决这个问题,可以使用互斥锁(std::mutex)来保护对账户余额的访问。

#include 
#include 
#include 
#include 

class BankAccount {
private:
    int accountID;
    std::string accountHolderName;
    double balance;
    std::mutex balanceMutex; // 互斥锁

public:
    BankAccount(int id, std::string name, double initialBalance) : accountID(id), accountHolderName(name), balance(initialBalance) {}

    int getAccountID() const {
        return accountID;
    }

    std::string getAccountHolderName() const {
        return accountHolderName;
    }

    double getBalance() const {
        std::lock_guard lock(balanceMutex); // 获取锁
        return balance;
    }

    void deposit(double amount) {
        if (amount > 0) {
            std::lock_guard lock(balanceMutex); // 获取锁
            balance += amount;
            std::cout << "存款成功,当前余额:" << balance << " (线程ID: " << std::this_thread::get_id() << ")" << std::endl;
        } else {
            std::cout << "存款金额必须大于0" << std::endl;
        }
    }

    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            std::lock_guard lock(balanceMutex); // 获取锁
            balance -= amount;
            std::cout << "取款成功,当前余额:" << balance << " (线程ID: " << std::this_thread::get_id() << ")" << std::endl;
        } else {
            std::cout << "取款失败,余额不足或取款金额无效" << std::endl;
        }
    }

    void printAccountInfo() const {
        std::lock_guard lock(balanceMutex); // 获取锁
        std::cout << "账户ID: " << accountID << std::endl;
        std::cout << "账户持有人姓名: " << accountHolderName << std::endl;
        std::cout << "账户余额: " << balance << std::endl;
    }
};

void performTransactions(BankAccount& account, int numTransactions) {
    for (int i = 0; i < numTransactions; ++i) {
        account.deposit(100.0);
        account.withdraw(50.0);
    }
}

int main() {
    BankAccount account(12345, "张三", 1000.0);

    // 创建多个线程进行并发操作
    std::thread thread1(performTransactions, std::ref(account), 1000);
    std::thread thread2(performTransactions, std::ref(account), 1000);

    // 等待线程完成
    thread1.join();
    thread2.join();

    // 打印最终账户信息
    account.printAccountInfo();

    return 0;
}

在这个例子中,std::mutex balanceMutex用于保护balance变量。 std::lock_guard是一个RAII(Resource Acquisition Is Initialization)风格的锁,它在构造时获取锁,在析构时释放锁,确保在任何情况下都能正确释放锁,即使发生异常。 通过使用互斥锁,可以避免多个线程同时修改balance变量,从而保证线程安全。

如何扩展银行账户系统,支持不同类型的账户(例如储蓄账户和支票账户)?

可以使用继承来实现不同类型的账户。 创建一个基类BankAccount,然后创建派生类SavingsAccount(储蓄账户)和CheckingAccount(支票账户),它们继承自BankAccount并添加特定于账户类型的属性和方法。

#include 
#include 

class BankAccount {
protected: // 修改为protected,允许派生类访问
    int accountID;
    std::string accountHolderName;
    double balance;

public:
    BankAccount(int id, std::string name, double initialBalance) : accountID(id), accountHolderName(name), balance(initialBalance) {}

    virtual ~BankAccount() {} // 虚析构函数

    int getAccountID() const {
        return accountID;
    }

    std::string getAccountHolderName() const {
        return accountHolderName;
    }

    double getBalance() const {
        return balance;
    }

    virtual void deposit(double amount) { // 虚函数
        if (amount > 0) {
            balance += amount;
            std::cout << "存款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "存款金额必须大于0" << std::endl;
        }
    }

    virtual void withdraw(double amount) { // 虚函数
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            std::cout << "取款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "取款失败,余额不足或取款金额无效" << std::endl;
        }
    }

    virtual void printAccountInfo() const { // 虚函数
        std::cout << "账户ID: " << accountID << std::endl;
        std::cout << "账户持有人姓名: " << accountHolderName << std::endl;
        std::cout << "账户余额: " << balance << std::endl;
    }
};

class SavingsAccount : public BankAccount {
private:
    double interestRate;

public:
    SavingsAccount(int id, std::string name, double initialBalance, double rate) : BankAccount(id, name, initialBalance), interestRate(rate) {}

    void addInterest() {
        double interest = balance * interestRate;
        deposit(interest);
        std::cout << "已添加利息:" << interest << std::endl;
    }

    void printAccountInfo() const override { // 重写
        BankAccount::printAccountInfo();
        std::cout << "利率: " << interestRate << std::endl;
    }
};

class CheckingAccount : public BankAccount {
private:
    double overdraftLimit;

public:
    CheckingAccount(int id, std::string name, double initialBalance, double limit) : BankAccount(id, name, initialBalance), overdraftLimit(limit) {}

    void withdraw(double amount) override { // 重写
        if (amount > 0 && (balance + overdraftLimit) >= amount) {
            balance -= amount;
            std::cout << "取款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "取款失败,超过透支额度或取款金额无效" << std::endl;
        }
    }

    void printAccountInfo() const override { // 重写
        BankAccount::printAccountInfo();
        std::cout << "透支额度: " << overdraftLimit << std::endl;
    }
};

int main() {
    SavingsAccount savingsAccount(11111, "王五", 2000.0, 0.05);
    CheckingAccount checkingAccount(22222, "赵六", 1500.0, 500.0);

    savingsAccount.printAccountInfo();
    savingsAccount.addInterest();
    savingsAccount.printAccountInfo();

    checkingAccount.printAccountInfo();
    checkingAccount.withdraw(2000.0); // 允许透支
    checkingAccount.printAccountInfo();

    return 0;
}

在这个例子中,SavingsAccount添加了interestRate属性和addInterest方法,而CheckingAccount添加了overdraftLimit属性并重写了withdraw方法以支持透支。 virtual关键字使得基类的方法可以被派生类重写,从而实现多态性。

如何将账户数据持久化到文件或数据库中?

可以使用文件或数据库来持久化账户数据。 对于简单的系统,可以使用文件存储。 对于更复杂的系统,可以使用数据库(例如SQLite、MySQL或PostgreSQL)。

使用文件存储:

#include 
#include 
#include 

class BankAccount {
private:
    int accountID;
    std::string accountHolderName;
    double balance;

public:
    BankAccount(int id, std::string name, double initialBalance) : accountID(id), accountHolderName(name), balance(initialBalance) {}

    int getAccountID() const {
        return accountID;
    }

    std::string getAccountHolderName() const {
        return accountHolderName;
    }

    double getBalance() const {
        return balance;
    }

    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            std::cout << "存款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "存款金额必须大于0" << std::endl;
        }
    }

    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            std::cout << "取款成功,当前余额:" << balance << std::endl;
        } else {
            std::cout << "取款失败,余额不足或取款金额无效" << std::endl;
        }
    }

    void printAccountInfo() const {
        std::cout << "账户ID: " << accountID << std::endl;
        std::cout << "账户持有人姓名: " << accountHolderName << std::endl;
        std::cout << "账户余额: " << balance << std::endl;
    }

    // 将账户数据保存到文件
    void saveToFile(std::ofstream& file) const {
        file << accountID << std::endl;
        file << accountHolderName << std::endl;
        file << balance << std::endl;
    }

    // 从文件加载账户数据
    void loadFromFile(std::ifstream& file) {
        file >> accountID;
        file.ignore(); // 忽略换行符
        std::getline(file, accountHolderName);
        file >> balance;
        file.ignore(); // 忽略换行符
    }
};

int main() {
    BankAccount account1(12345, "张三", 1000.0);

    // 保存账户到文件
    std::ofstream outFile("accounts.txt");
    if (outFile.is_open()) {
        account1.saveToFile(outFile);
        outFile.close();
        std::cout << "账户已保存到文件" << std::endl;
    } else {
        std::cerr << "无法打开文件进行写入" << std::endl;
    }

    // 从文件加载账户
    BankAccount account2(0, "", 0.0); // 创建一个空账户
    std::ifstream inFile("accounts.txt");
    if (inFile.is_open()) {
        account2.loadFromFile(inFile);
        inFile.close();
        std::cout << "账户已从文件加载" << std::endl;
        account2.printAccountInfo();
    } else {
        std::cerr << "无法打开文件进行读取" << std::endl;
    }

    return 0;
}

这个例子展示了如何使用ofstreamifstream将账户数据保存到文件和从文件加载账户数据。 需要注意的是,文件格式需要仔细设计,以确保数据的正确读取和写入。 此外,还需要处理文件打开失败等错误情况。

使用数据库存储:

使用数据库需要引入相应的数据库库,例如SQLite的sqlite3库。 这里只提供一个概念性的示例,具体的实现需要根据选择的数据库和库进行调整。

// (伪代码,需要引入数据库库)
/*
#include 

int main() {
    sqlite3 *db;
    int rc = sqlite3_open("bank.db", &db);

    if (rc) {
        std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
        return 1;
    }

    // 创建表
    const char *createTableSQL = "CREATE TABLE IF NOT EXISTS accounts ("
                                  "accountID INTEGER PRIMARY KEY,"
                                  "accountHolderName TEXT,"
                                  "balance REAL);";

    rc = sqlite3_exec(db, createTableSQL, 0, 0, 0);
    if (rc != SQLITE_OK) {
        std::cerr << "创建表失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_close(db);
        return 1;
    }

    // 插入数据
    const char *insertSQL = "INSERT INTO accounts (accountID, accountHolderName, balance) VALUES (12345, '张三', 1000.0);";
    rc = sqlite3_exec(db, insertSQL, 0, 0, 0);
    if (rc != SQLITE_OK) {
        std::cerr << "插入数据失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_close(db);
        return 1;
    }

    // 查询数据
    const char *selectSQL = "SELECT * FROM accounts;";
    sqlite3_stmt *stmt;
    rc = sqlite3_prepare_v2(db, selectSQL, -1, &stmt, 0);
    if (rc != SQLITE_OK) {
        std::cerr << "查询失败: " << sqlite3_errmsg(db) << std::endl;
        sqlite3_close(db);
        return 1;
    }

    while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
        int accountID = sqlite3_column_int(stmt, 0);
        const char *accountHolderName = (const char*)sqlite3_column_text(stmt, 1);
        double balance = sqlite3_column_double(stmt, 2);

        std::cout << "账户ID: " << accountID << std::endl;
        std::cout << "账户持有人姓名: " << accountHolderName << std::endl;
        std::cout << "账户余额: " << balance << std::endl;
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);

    return 0;
}
*/

这个伪代码展示了如何使用SQLite数据库存储账户数据。 你需要安装SQLite库,并根据实际情况调整代码。 使用数据库可以提供更好的数据管理和查询功能,但也增加了系统的复杂性。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
C++类构造与析构函数详解
C++类构造与析构函数详解

C++类构造与析构函数详解 C++这门语言,可以说是从C语言这棵大树上衍生出的高级果实,如今的应用普及度有目共睹。作为一种静态类型的通用编程语言,它厉害的地方在于融合了多种编程哲学——无论是传统的面向过程,还是主流的面向对象,乃至数据抽象、泛型编程这些高级概念,它都能很好地支持。正因为这份卓越的扩展

C++中std::upper
C++中std::upper

C++中std::upper_bound用法解析 在C++标准模板库(STL)的算法工具箱里,upper_bound() 绝对算得上是一把精准的“探针”。它的核心任务很明确:在一个已经排好序的区间 [first, last) 内,帮你快速定位到第一个**严格大于**指定值 value 的那个元素。这

C++常对象与成员解析
C++常对象与成员解析

C++中“常”概念全景解析:从对象、成员到指针与引用 在C++的世界里,“常量性”是一个强大的保障机制。它不仅仅是一个const关键字那么简单,而是构建健壮、安全程序的重要基石。今天,我们就来系统梳理一下围绕“常”的一系列概念:常成员、常对象、常指针与常引用。理解它们,是写出高质量C++代码的关键一

using namespace 使用中遇到的问题怎么解决
using namespace 使用中遇到的问题怎么解决

命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,

c语言函数递归 实操经验总结:这些技巧很实用
c语言函数递归 实操经验总结:这些技巧很实用

理解递归的基本原理在C语言中,递归是一种函数调用自身的编程技术。要掌握它,首先需要理解其核心思想:将一个复杂的大问题,分解为一个或几个与原问题相似但规模更小的子问题,直到子问题足够简单,可以直接求解。这个过程通常包含两个关键部分:递归出口和递归体。递归出口定义了问题何时不再继续分解,即最简单、可直接

c语言函数递归 怎么选?常见方案对比分析
c语言函数递归 怎么选?常见方案对比分析

递归函数的基本概念与适用场景在C语言编程中,递归是一种函数调用自身的编程技巧。它并非适用于所有问题,但在处理某些具有自相似结构的问题时,能提供极其清晰和优雅的解决方案。递归的核心思想是将一个大规模问题分解为一个或多个同类型但规模更小的子问题,直到子问题简单到可以直接求解。典型的适用场景包括树形结构的

Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解
Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解

理解内存管理的基石在Objective-C的编程世界中,内存管理是开发者必须掌握的核心技能之一。它直接关系到应用的性能、稳定性与资源利用效率。与一些采用自动垃圾回收机制的语言不同,Objective-C在很长一段时间里,依赖一套基于引用计数的、需要开发者部分介入的管理规则。这套规则的核心思想是明确的

如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏
如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏

理解 dealloc 的角色与时机在 iOS 应用开发中,内存管理是保障应用性能与稳定性的基石。dealloc 方法是 Objective-C 中对象生命周期结束时的关键回调,它标志着对象即将被系统回收内存。正确理解其触发时机至关重要:当一个对象的引用计数降为零时,运行时系统会自动调用该对象的 de

深入理解 Objective-C 中的 dealloc 方法:内存管理核心机制
深入理解 Objective-C 中的 dealloc 方法:内存管理核心机制

内存管理的基石在Objective-C的世界里,内存管理是开发者必须掌握的核心技能之一。作为一门在手动引用计数(MRC)时代诞生的语言,Objective-C要求程序员对对象的生命周期有清晰的认识。dealloc方法正是这一生命周期中至关重要的终点站。它是一个实例方法,当对象的引用计数降为零时,系统

理解 native2ascii:Java 国际化开发中的字符编码工具
理解 native2ascii:Java 国际化开发中的字符编码工具

native2ascii 工具的基本定位在Ja va应用程序的国际化与本地化开发过程中,处理非拉丁字符集是一个常见且关键的环节。Ja va内部使用Unicode字符集来统一表示全球各种语言的文字,但其属性文件(.properties)在历史上要求使用ASCII编码,或者更准确地说,要求非ASCII字

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
灵活计算器
灵活计算器
macOS/iOS/Android

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师
macOS

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

WINDOWS 更多
Windows 10
Windows 10
Windows

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘
Windows/macOS/iOS/Android

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。