Skip to content
Snippets Groups Projects
Commit e247c0b3 authored by Guttmann, Michael's avatar Guttmann, Michael
Browse files

added bank-example

parent 5600e939
No related branches found
No related tags found
No related merge requests found
#ifndef ACCOUNT_HPP
#define ACCOUNT_HPP
class Account
{
private:
int euros_;
public:
Account() : euros_(0) {}
Account(const Account& copy) : euros_(copy.euros_) {}
Account& operator=(const Account& rhs)
{
if (this != &rhs)
euros_ = rhs.euros_;
return *this;
}
~Account() = default;
int getEuros() const { return euros_; }
void changeEurosBy(int difference) { euros_ += difference; }
};
#endif // ACCOUNT_HPP
#ifndef BANK_HPP
#define BANK_HPP
#include "Account.hpp"
#include <stdexcept>
#include <iostream>
class Bank
{
private:
Account* account_;
int pin_code_;
public:
// (*) References / Pointers as a parameters stay valid outside
// No copy -> attributes of classes can be modified from outside
Bank(Account* account, int pin_code) : account_(new Account(*account)), pin_code_(pin_code)
{
// Checks in public methods that are called with parameters
if (pin_code_ < 0x1000 || pin_code_ >= 0x10000)
throw std::runtime_error("Der Pin-Code ist zu kurz / zu lang!");
}
Bank(const Bank&) = delete;
Bank& operator=(const Bank&) = delete;
~Bank() { delete account_; }
bool verifyPinCode() const
{
// Very bad using just std::cin
int pin_code;
std::cout << "Enter your pin: ";
std::cin.unsetf(std::ios::dec);
std::cin.unsetf(std::ios::hex);
std::cin.unsetf(std::ios::oct);
std::cin >> pin_code;
return pin_code == pin_code_;
}
// (#) Methods that return references / pointers may screw up
// the concept of encapsulation
Account const* getAccount()
{
if (!verifyPinCode())
throw std::runtime_error("Der Pin-Code ist nicht gültig!");
return account_;
}
// These two methods are safe, as they do not return a reference / pointer
int getAccountEuros() const
{
if (!verifyPinCode())
throw std::runtime_error("Der Pin-Code ist nicht gültig!");
return account_->getEuros();
}
void changeAccountEurosBy(int euros)
{
if (!verifyPinCode())
throw std::runtime_error("Der Pin-Code ist nicht gültig!");
account_->changeEurosBy(euros);
}
};
#endif // BANK_HPP
#include "Bank.hpp"
#include "Account.hpp"
int main(void)
{
int account_state;
//------------------------------------------------------------------------------------------------
std::cout << "\nÜberprüfungen in Settern / Konstruktoren!" << std::endl;
Account* my_account = new Account;
// Bank my_bank(my_account, 0x1337abc); // not valid after check in constructor
Bank my_bank(my_account, 0x1337); // this is okay
account_state = my_bank.getAccountEuros(); // pin-code check
std::cout << "Kontostand: " << account_state << std::endl;
//------------------------------------------------------------------------------------------------
std::cout << "\nPointer als Übergabeparameter!" << std::endl;
my_account->changeEurosBy(-100); // account from parameters, no pin-code check (* in Bank.hpp)
account_state = my_account->getEuros(); // no pin-code check
std::cout << "falscher Kontostand: " << account_state << std::endl;
account_state = my_bank.getAccountEuros(); // pin-code check
std::cout << "richtiger Kontostand: " << account_state << std::endl;
//------------------------------------------------------------------------------------------------
std::cout << "\nPointer als Rückgabewerte!" << std::endl;
Account const* my_second_account = my_bank.getAccount(); // getter of account, (# in Bank.hpp)
// my_second_account->changeEurosBy(-500); // invalid, if pointer is const; no pin-code check
Account* hacked_account = const_cast<Account*>(my_second_account); // don't use const_cast
hacked_account->changeEurosBy(-500); // now valid and no pin-code check
account_state = my_second_account->getEuros(); // no pin-code check
std::cout << "falscher Kontostand: " << account_state << std::endl;
account_state = my_bank.getAccountEuros(); // pin-code check
std::cout << "richtiger Kontostand: " << account_state << std::endl;
// Solution: Don't return a reference / pointer, rather try to provide a method
// to handle everything inside of the class. If the reference / pointer
// has to be returned anyway, make it at least const.
//------------------------------------------------------------------------------------------------
std::cout << "\nReinterpret Cast!" << std::endl;
std::cout << "Größe der Klasse: " << sizeof(my_bank) << std::endl;
uint8_t* array = reinterpret_cast<uint8_t*>(&my_bank); // interpret the class as a byte-array
for (size_t i = 0; i < sizeof(my_bank); i += 4)
{
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i]) << " ";
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i + 1]) << " ";
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i + 2]) << " ";
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i + 3]) << std::endl;
}
std::cout << std::endl;
array[8] = 0x38; // change a byte of the class (no encapsulation)
for (size_t i = 0; i < sizeof(my_bank); i += 4)
{
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i]) << " ";
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i + 1]) << " ";
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i + 2]) << " ";
std::cout.width(2);
std::cout << std::hex << static_cast<int>(array[i + 3]) << std::endl;
}
std::cout << std::endl;
account_state = my_bank.getAccountEuros();
std::cout << "richtiger Kontostand: " << std::dec << account_state << std::endl << std::endl;
// Don't do this in the practicals ever! :D
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment