#include <functional>
#include <iostream>
#include <memory>
#include <vector>
#include "deposit_withdraw_account.h"
#include "withdraw_account.h"
void ShowBalance(const char prefix, const std::unique_ptr<Account> &account)
{
std::cout << prefix << " Balance (" << account->GetId() << "): "
<< account->GetBalance() << " EUR\n";
}
void CreateAccounts(std::vector<std::unique_ptr<Account>> *accounts)
{
accounts->emplace_back(new DepositAccount{"0001"});
auto interest_account = new InterestAccount{"0002"};
interest_account->SetInterestRate(0.0025);
accounts->emplace_back(interest_account);
auto withdraw_account = new WithdrawAccount{"0003"};
withdraw_account->SetInterestRate(0.001);
accounts->emplace_back(withdraw_account);
accounts->emplace_back(new DepositWithdrawAccount{"0004"});
}
template <class T>
void Process(const std::vector<std::unique_ptr<Account>> &accounts,
std::function<void(T *)> action)
{
for (auto &account : accounts) {
auto prefix = '-';
const auto special_account = dynamic_cast<T *>(account.get());
if (special_account != nullptr) {
action(special_account);
prefix = '+';
}
ShowBalance(prefix, account);
}
}
void Deposit(const std::vector<std::unique_ptr<Account>> &accounts)
{
auto counter = 0;
Process<DepositAccount>(accounts, [&counter](auto account) {
account->Deposit(4200.23 + counter++);
});
}
void PayInterest(const std::vector<std::unique_ptr<Account>> &accounts)
{
Process<InterestAccount>(accounts,
[](auto account) { account->PayInterest(); });
}
void Withdraw(const std::vector<std::unique_ptr<Account>> &accounts)
{
Process<WithdrawAccount>(accounts,
[](auto account) { account->Withdraw(10.0); });
}
int main()
{
std::vector<std::unique_ptr<Account>> accounts;
std::cout.precision(2);
std::cout.setf(std::ios_base::fixed);
std::cout << "Create accounts ...\n";
CreateAccounts(&accounts);
std::cout << "\n\nDeposit ...\n";
Deposit(accounts);
std::cout << "\n\nPay interest ...\n";
PayInterest(accounts);
std::cout << "\n\nWithdraw ...\n";
Withdraw(accounts);
}
#ifndef ACCOUNT_H_
#define ACCOUNT_H_
#include <string>
#include <utility>
class Account {
protected:
double balance_{};
private:
std::string id_;
public:
explicit Account(std::string id) noexcept : id_{std::move(id)} {}
virtual ~Account() = default;
auto GetBalance() const noexcept { return balance_; }
auto SetBalance(double amount) noexcept { balance_ = amount; }
auto GetId() const noexcept { return id_; }
};
#endif // ACCOUNT_H_
#ifndef DEPOSIT_ACCOUNT_H_
#define DEPOSIT_ACCOUNT_H_
#include "account.h"
class DepositAccount : public Account {
public:
using Account::Account;
auto Deposit(double amount) noexcept {
if (amount <= 0.0) return;
balance_ += amount;
}
};
#endif // DEPOSIT_ACCOUNT_H_
#ifndef DEPOSIT_WITHDRAW_ACCOUNT_H_
#define DEPOSIT_WITHDRAW_ACCOUNT_H_
#include "account.h"
class DepositWithdrawAccount : public Account {
public:
using Account::Account;
};
#endif // DEPOSIT_WITHDRAW_ACCOUNT_H_
#ifndef INTEREST_ACCOUNT_H_
#define INTEREST_ACCOUNT_H_
#include "deposit_account.h"
class InterestAccount : public DepositAccount {
private:
double interest_rate_{};
public:
using DepositAccount::DepositAccount;
auto GetInterestRate() const noexcept {
return interest_rate_;
}
auto SetInterestRate(double interest_rate) noexcept {
interest_rate_ = interest_rate;
}
auto PayInterest() noexcept {
const auto interest = balance_ * interest_rate_;
balance_ += interest;
}
};
#endif // INTEREST_ACCOUNT_H_
#ifndef WITHDRAW_ACCOUNT_H_
#define WITHDRAW_ACCOUNT_H_
#include "interest_account.h"
class WithdrawAccount : public InterestAccount {
public:
using InterestAccount::InterestAccount;
auto Withdraw(double amount) noexcept {
if (amount > balance_) return;
balance_ -= amount;
}
};
#endif // WITHDRAW_ACCOUNT_H_