Cześć mam problem z vectorem przechowujący wskaźniki shared_ptr klasy bazowej. Chce przez analogie do wskaźników surowych wywołać odpowiednie metody klas pochodnych, ale nie wiem jak sobie poradzić. Próbowałem z static_cast albo dynamic_pointer_cast ale nie działa.
Dzięki za pomoc ;)
header.h
#ifndef ACCOUNT_H_
#define ACCOUNT_H_
#include <iostream>
#include <string>
#include <memory>
// abstrakcyjna klasa bazowa
class AcctABC
{
public:
AcctABC(const std::string & s = "brak", long an = -1, double bal = 0.0);
void Deposit(double amt);
virtual void Withdraw(double amt) = 0;
double Balance() const { return balance; }
virtual void ViewAcct() const = 0;
virtual ~AcctABC() {}
private:
std::string fullName;
long acctNum;
double balance;
protected:
struct Formatting
{
std::ios_base::fmtflags flag;
std::streamsize pr;
};
const std::string & FullName() const { return fullName; }
long AcctNum() const { return acctNum; }
Formatting SetFormat() const;
void Restore(Formatting & f) const;
};
// klasa do obsługi rachunku Brass
class Brass : public AcctABC
{
public:
Brass(const std::string & s = "brak", long an = -1, double bal = 0.0) :
AcctABC(s, an, bal)
{}
virtual void Withdraw(double amt) override;
virtual void ViewAcct() const override;
virtual ~Brass() {}
};
// klasa do obsługi rachunku BrassPlus
class BrassPlus : public AcctABC
{
private:
std::shared_ptr<BrassPlus> shptr;
double maxLoan;
double rate;
double owesBank;
public:
BrassPlus(const std::string & s = "brak", long an = -1, double bal = 0.0, double ml = 500, double r = 0.10);
BrassPlus(const Brass & ba, double ml = 500, double r = 0.1);
virtual void ViewAcct() const override;
virtual void Withdraw(double amt) override;
void ResetMax(double m) { maxLoan = m; }
void ResetRate(double r) { rate = r; }
void ResetOwes() { owesBank = 0; }
};
#endif
def.cpp
#include <iostream>
#include "header.h"
using std::cout;
using std::ios_base;
using std::endl;
using std::string;
// abstrakcyjna klasa bazowa
AcctABC::AcctABC(const string & s, long an, double bal) :
fullName(s),
acctNum(an),
balance(bal)
{
}
void AcctABC::Deposit(double amt)
{
if (amt < 0)
cout << "Nie możesz wpłacić ujemnej kwoty; "
<< "Wpłata anulowana.\n";
else
balance += amt;
}
void AcctABC::Withdraw(double amt)
{
balance -= amt;
}
// metody chronione, zajmujące się formatowaniem
AcctABC::Formatting AcctABC::SetFormat() const
{
// ustawia format w postaci ###.##
Formatting f;
f.flag =
cout.setf(ios_base::fixed, ios_base::floatfield);
f.pr = cout.precision(2);
return f;
}
void AcctABC::Restore(Formatting & f) const
{
cout.setf(f.flag, ios_base::floatfield);
cout.precision(f.pr);
}
// metody klasy Brass
void Brass::Withdraw(double amt)
{
if (amt < 0)
cout << "Nie można wypłacić ujemnej kwoty; "
<< "Wypłata anulowana.\n";
else if (amt <= Balance())
AcctABC::Withdraw(amt);
else
cout << "Żądana wartość " << amt
<< " zł przekracza dostępne środki.\n"
<< "Wypłata anulowana.\n";
}
void Brass::ViewAcct() const
{
Formatting f = SetFormat();
cout << "Właściciel rachunku Brass: " << FullName() << endl;
cout << "Numer rachunku: " << AcctNum() << endl;
cout << "Stan konta: " << Balance() << " zł" << endl;
Restore(f);
}
// metody klasy BrassPlus
BrassPlus::BrassPlus(const string & s, long an, double bal, double ml, double r) :
AcctABC(s, an, bal),
maxLoan(ml),
owesBank(0.0),
rate(r)
{}
BrassPlus::BrassPlus(const Brass & ba, double ml, double r) :
AcctABC(ba), // używa niejawnego konstruktora kopiującego
maxLoan(ml),
owesBank(0.0),
rate(r)
{}
void BrassPlus::ViewAcct() const
{
Formatting f = SetFormat();
cout << "Właściciel rachunku BrassPlus: " << FullName() << endl;
cout << "Numer rachunku: " << AcctNum() << endl;
cout << "Stan konta: " << Balance() << " zł" << endl;
cout << "Limit debetu: " << maxLoan << " zł" << endl;
cout << "Kwota zadłużenia: " << owesBank << " zł" << endl;
cout.precision(3);
cout << "Stopa oprocentowania: " << 100 * rate << "%\n";
Restore(f);
}
void BrassPlus::Withdraw(double amt)
{
Formatting f = SetFormat();
double bal = Balance();
if (amt <= bal)
AcctABC::Withdraw(amt);
else if (amt <= bal + maxLoan - owesBank)
{
double advance = amt - bal;
owesBank += advance * (1.0 + rate);
cout << "Zadłużenie faktyczne: " << advance << " zł" << endl;
cout << "Odsetki: " << advance * rate << " zł" << endl;
Deposit(advance);
AcctABC::Withdraw(amt);
}
else
cout << "Przekroczony limit debetu. Operacja anulowana.\n";
Restore(f);
}
test.cpp
#include "header.h"
#include <vector>
#include <algorithm>
const int CLIENTS = 2;
int main()
{
using std::cin;
using std::cout;
using std::endl;
using std::vector;
std::string temp;
long tempnum;
double tempbal;
char kind;
vector<std::shared_ptr<AcctABC>> pClientVector;
for (int i = 0; i < CLIENTS; i++)
{
cout << "Podaj imię i nazwisko klienta: ";
getline(cin, temp);
cout << "Podaj numer rachunku klienta: ";
cin >> tempnum;
cout << "Podaj początkowy stan konta: $";
cin >> tempbal;
cout << "Wpisz 1 dla rachunku Brass lub "
<< "2 dla rachunku BrassPlus: ";
while (cin >> kind && (kind !='1' && kind != '2'))
cout << "Wpisz 1 lub 2: ";
if(kind == '1')
{
auto p_client1(std::make_shared<Brass>(temp, tempnum, tempbal));
pClientVector.push_back(p_client1);
}
else if(kind =='2')
{
double tmax, trate;
cout << "Podaj limit debetu: ";
cin >> tmax;
cin.get();
cout << "Podaj stopę oprocentowania "
<< "w postaci ułamka dziesiętnego: ";
cin >> trate;
auto p_client2(std::make_shared<BrassPlus>(temp, tempnum, tempbal, tmax, trate));
pClientVector.push_back(p_client2);
}
while (cin.get() != '\n')
continue;
}
cout << endl;
for(auto p=pClientVector.begin(); p != pClientVector.end(); p++)
{
auto brassPointer = std::make_shared<Brass>();
auto brassPlusPointer= std::make_shared<BrassPlus>();
if (brassPointer = dynamic_cast<Brass>(p))
{
}
}
//for (int i = 0; i < CLIENTS; i++) //Jeżeli zastosujemy surowe wskaźniki
//{
// p_clients[i]->ViewAcct();
// cout << endl;
//}
cout << "Gotowe.\n";
return 0;
}
Link do kompilatora online z kodem wstawionym:
https://onlinegdb.com/ryVjcnF_z