C++ Code Example: Wallet System with Operator Overloading & RAII

C++ has several unique object-oriented programming (OOP) features that make it stand out from other languages. In this example, we will explore:

Encapsulation – Using private members and getter/setter functions.
Composition – Structuring objects using other objects.
Operator Overloading – Customizing operations like + or == for user-defined classes.
Static Members – Using static variables and methods to maintain shared data.
RAII (Resource Acquisition Is Initialization) – Managing resources with constructors & destructors.


C++ Code Example: Wallet System with Operator Overloading & RAII

#include <iostream>
#include <vector>

using namespace std;

// Class representing a Wallet
class Wallet {
private:
    double balance;

public:
    // Constructor with Default Value
    Wallet(double initialBalance = 0.0) : balance(initialBalance) {
        cout << "Wallet created with balance: $" << balance << endl;
    }

    // Deposit Money
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            cout << "Deposited: $" << amount << " | New Balance: $" << balance << endl;
        } else {
            cout << "Invalid deposit amount!" << endl;
        }
    }

    // Withdraw Money
    void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            cout << "Withdrew: $" << amount << " | Remaining Balance: $" << balance << endl;
        } else {
            cout << "Invalid withdrawal or insufficient funds!" << endl;
        }
    }

    // Operator Overloading: Add Wallets Together
    Wallet operator+(const Wallet& other) {
        return Wallet(this->balance + other.balance);
    }

    // Operator Overloading: Compare Wallets
    bool operator==(const Wallet& other) {
        return this->balance == other.balance;
    }

    // Get the balance (Encapsulation)
    double getBalance() const {
        return balance;
    }

    // Destructor (RAII - Resource Cleanup)
    ~Wallet() {
        cout << "Wallet with balance $" << balance << " is being destroyed!" << endl;
    }
};

// Class to Manage All Wallets (Composition)
class WalletManager {
private:
    vector<Wallet> wallets; // Stores multiple wallet objects
    static int totalWallets; // Static variable shared across all instances

public:
    // Add a wallet to the manager
    void addWallet(double initialBalance) {
        wallets.push_back(Wallet(initialBalance));
        totalWallets++;
    }

    // Show all wallets
    void displayWallets() {
        cout << "\n--- Wallet Balances ---\n";
        for (size_t i = 0; i < wallets.size(); i++) {
            cout << "Wallet " << i + 1 << ": $" << wallets[i].getBalance() << endl;
        }
    }

    // Static Function: Get the Total Number of Wallets
    static int getTotalWallets() {
        return totalWallets;
    }
};

// Initialize Static Variable
int WalletManager::totalWallets = 0;

// Main Function
int main() {
    Wallet w1(100.0);  // Create a wallet with $100
    Wallet w2(50.0);   // Create a wallet with $50

    w1.deposit(20.0);  // Deposit $20 into wallet 1
    w2.withdraw(10.0); // Withdraw $10 from wallet 2

    // Operator Overloading
    Wallet w3 = w1 + w2; // Combine balances
    cout << "\nMerged Wallet Balance: $" << w3.getBalance() << endl;

    // Compare Wallets
    if (w1 == w2) {
        cout << "Both wallets have the same balance!\n";
    } else {
        cout << "Wallets have different balances.\n";
    }

    // Using WalletManager
    WalletManager manager;
    manager.addWallet(200.0);
    manager.addWallet(300.0);
    manager.displayWallets();

    cout << "\nTotal Wallets Created: " << WalletManager::getTotalWallets() << endl;

    return 0;
}

Expected Output

Wallet created with balance: $100
Wallet created with balance: $50
Deposited: $20 | New Balance: $120
Withdrew: $10 | Remaining Balance: $40

Wallet created with balance: $160
Merged Wallet Balance: $160
Wallets have different balances.

Wallet created with balance: $200
Wallet created with balance: $300

--- Wallet Balances ---
Wallet 1: $200
Wallet 2: $300

Total Wallets Created: 2
Wallet with balance $300 is being destroyed!
Wallet with balance $200 is being destroyed!
Wallet with balance $160 is being destroyed!
Wallet with balance $40 is being destroyed!
Wallet with balance $120 is being destroyed!

Key Features Demonstrated

1️⃣ Encapsulation

  • Private balance variable ensures controlled access.
  • Public methods (deposit(), withdraw(), getBalance()) enforce safe operations.

2️⃣ Composition Instead of Inheritance

  • WalletManager contains multiple Wallet objects but does not inherit from Wallet.

3️⃣ Operator Overloading

  • + operator merges two wallets.
  • == operator compares balances of two wallets.

4️⃣ Static Members

  • totalWallets keeps track of all created wallets.
  • static int getTotalWallets() allows class-wide access.

5️⃣ RAII (Resource Acquisition Is Initialization)

  • Constructor initializes wallets automatically.
  • Destructor (~Wallet()) ensures cleanup, displaying messages when wallets go out of scope.

Why Is This Example Unique?

Avoids Inheritance & Polymorphism but still showcases strong OOP principles.
Uses Operator Overloading to make object interactions more natural.
Static Members allow global tracking of wallets.
RAII ensures safe resource management without memory leaks.

This example highlights powerful OOP features specific to C++, making it ideal for understanding object-oriented design.