So I am trying to append new accounts with vector which in Class Bank. For new account such as Class checking and Class saving that are derived from Class bankaccount.
I could not figure out what type of parameter I have to put in void addaccount() parameter so I can use it in main function below. Is it possible way I do not have to use template? From my understanding that is only option as I am using it to call multiple class type.
Bank b;
b.addAccount(new CheckingAccount(12345, 18));
#include "pch.h"
#include <iostream>
#include <vector>
using namespace std;
class bankaccount {
int acctnum;
double balance;
public:
bankaccount(double newbalance=0.00, int newacctnum=0) { balance = newbalance; acctnum = newacctnum; }
int getacctnum() { return acctnum;}
double getbalance() { return balance; }
double setbalance(double newmoney) { balance += newmoney; }
void deposit(double newdepo) {
balance=getbalance() + newdepo;
}
void deposit(double newwith) {
balance = getbalance() - newwith;
}
};
class Savingaccount: public bankaccount
{
Savingaccount(int newacctnum, double rate):bankaccount(){
acctnum = newacctnum;
balance = getbalance() * (1 + rate);
};
void deposit(double newdepo) {
balance = getbalance() + newdepo;
}
void deposit(double newwith) {
balance = getbalance() - newwith;
}
};
class Checkingaccount : public bankaccount {
Checkingaccount(int newacctnum, double rate);
void deposit(double newdepo) {
balance = getbalance() + newdepo;
}
void deposit(double newwith) {
balance = getbalance() - newwith;
}
};
template <class T>
class Bank {
vector<T> x;
public:
void addaccount(T *temp);
void runmonthly();
};
int main() {
Bank b;
b.addAccount(new CheckingAccount(12345, 18)); //$18 monthly fee
b.addAccount(new SavingsAccount(12346, 0.02)); // 2% per month interest!
}
In your example, there is no need for templates. You can use runtime polymorphism and you were already half way there. However, you code had a lot of errors and I fixed multiple of them. Nonetheless, I still might have missed something. Please, next time, make sure that there are no bugs in your code unrelated to your question here (e.g. wrong names, multiple functions with the same signature in a class, etc.). Here is a working code, see the annotations in the code for explanations (live demo):
#include <iostream>
#include <vector>
#include <string>
// We need this for std::unique_ptr
#include <memory>
using namespace std;
class bankaccount {
// To access the members from base classes, make them protected.
protected:
int acctnum;
double balance;
public:
bankaccount(double newbalance=0.00, int newacctnum=0) { balance = newbalance; acctnum = newacctnum; }
int getacctnum() { return acctnum;}
double getbalance() { return balance; }
// The return type should be void.
void setbalance(double newmoney) { balance += newmoney; }
// Make this virtual, to be able to choose the correct function from derived
// classes via runtime polymorphism.
virtual void deposit(double newdepo) {
balance=getbalance() + newdepo;
}
// Added this to demonstrate runtime polymorphism.
virtual string accounttype () const {return "base";}
// I removed the second deposit method, as you are not allowed to
// have multiple functions with the same signature. Btw both functions did
// the same.
// When having virtual functions, you should also have a virtual destructor.
virtual ~bankaccount() = default;
};
class Savingaccount: public bankaccount
{
// The functions above should be part of the public interface.
public:
Savingaccount(int newacctnum, double rate):bankaccount(){
acctnum = newacctnum;
balance = getbalance() * (1 + rate);
};
// The override keyword specifies, that a virtual function of the base
// class is going to be overwritten.
virtual void deposit(double newdepo) override {
balance = getbalance() + newdepo;
}
// Added this to demonstrate runtime polymorphism.
virtual string accounttype () const {return "saving";}
// When having virtual functions, you should also have a virtual destructor.
virtual ~Savingaccount() = default;
};
class Checkingaccount : public bankaccount
{
// The functions above should be part of the public interface.
public:
Checkingaccount(int newacctnum, double rate):bankaccount() {/*TODO*/};
// Make this function virtual:
virtual void deposit(double newdepo) override {
balance = getbalance() + newdepo;
}
// Added this to demonstrate runtime polymorphism.
virtual string accounttype () const override {return "checking";}
// When having virtual functions, you should also have a virtual destructor.
virtual ~Checkingaccount() = default;
};
class Bank {
vector<unique_ptr<bankaccount>> x;
public:
auto& getaccounts() const {return x;}
// Now, pass a pointer to the base class. The correct functions deposit
// and accounttype will be called as you marked them in the base class as
// virtual.
void addaccount(bankaccount *temp) {x.emplace_back(temp);}
void runmonthly() {/*TODO*/};
};
int main() {
Bank b;
b.addaccount(new Checkingaccount(12345, 18)); //$18 monthly fee
b.addaccount(new Savingaccount(12346, 0.02)); // 2% per month interest!
for (const auto& account : b.getaccounts())
std::cout << account->accounttype() << std::endl;
}
Note that there is still a lot of room for improvement. For instance, you should check if an account with a certain number exists before adding it. If you don't intend to further derive from Checkingaccount or Savingaccount you can mark them as final, etc.
Related
I have declared a class Products and another class CD the class CD is inheriting the class Products.
Now I have declared an constructor to update the value of the. and I am getting an error
#include <iostream>
#include <string>
class Products
{
private:
std::string name;
std::string type;
double price;
public:
virtual std::string getname();
virtual double getprice();
virtual void show();
std::string gettype()
{
return type;
}
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(std::string sname,double sprice,std::string sartist,std::string sstudio)
{
this->type = "CD";
this->name = sname ;
this->price = sprice;
this->artist = sartist;
this->studio = sstudio;
}
void show()
{
std::cout<<"\nName of the CD:\t"<<this->name;
std::cout<<"\nArtist of the CD:\t"<<this->artist;
std::cout<<"\nStudio of the CD:\t"<<this->studio;
std::cout<<"\nPrice of the cd:\t"<<this->price;
}
};
int main()
{
CD obj("Oceans",49,"somesinger","somestudio");
}
ERROR :
In constructor 'CD::CD(std::string, double, std::string)';
'std::string Products::type' is private within this context
this->type="CD";
'std::string Products::name' is private within this context
this->name=sname;
'double Products::price' is private within this context
this->price= sprice;
Basically it is not giving error for the private data members of the CD class but just the data members that are being inherited from Products Class
#include <iostream>
#include <string>
class Products
{
private:
std::string m_name;
std::string m_type;
double m_price;
public:
// No need for your setters/getters to be virtual
// if the derived class won't override anything or not
const std::string& getType() const { return m_type; }
const std::string& getName() const { return m_name; }
double getPrice() const { return m_price; }
void setType(const std::string& new_type) { m_type = new_type; }
void setName(const std::string& new_name) { m_name = new_name; }
void setPrice(double new_price) { m_price = new_price; }
// Force derived class to override function
virtual void show() = 0;
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(std::string sname,double sprice,std::string sartist,std::string sstudio)
{
this->setType("CD");
this->setName(sname) ;
this->setPrice(sprice);
this->artist = sartist;
this->studio = sstudio;
}
void show()
{
std::cout<<"\nName of the CD:\t"<<this->getName();
std::cout<<"\nArtist of the CD:\t"<<this->artist;
std::cout<<"\nStudio of the CD:\t"<<this->studio;
std::cout<<"\nPrice of the cd:\t"<<this->getPrice();
}
};
int main()
{
CD obj("Oceans",49,"somesinger","somestudio");
obj.show();
}
I want you to understand some changes here. First the removal of virtual keyword. In your case the setters/getters had no need to be virtual, as they were not being overriden or didn't have a need to be based on the current example. Second, the setters/getters are setup to access the private members accordingly. We now use these functions within class CD. Also we changed the function show() to be pure virtual notice the = 0 at the end. I added a comment saying this forces derived classes to override the function. Lastly, your main wasn't doing anything so I added a obj.show() to actually print something.
In this solution, I've added a constructor for Products, and CD's constructor calls it to initialize the members that are private to Products.
I removed the virtual on getName and getPrice since these features don't change other products.
show remains virtual, and I split it into a piece in Products and a piece in CD so they each display their respective fields. This separates the printing according to where the variables are, so for example, another class derived from Products wouldn't have to reimplement printing of name and price.
#include <iostream>
#include <string>
class Products
{
private:
std::string name;
std::string type;
double price;
public:
std::string getname(); // Does not need to be virtual, as it's not overriden
double getprice(); // Also does not need to be virtual
virtual void show() const {
std::cout<<"\nName of the " << type << ":\t"<<this->name;
std::cout<<"\nPrice of the " << type << ":\t"<<this->price;
};
Products (const std::string &stype, double sprice, const std::string &sname)
: name (sname), type (stype), price (sprice) {
}
std::string gettype() const
{
return type;
}
};
class CD: public Products
{
private:
std::string artist;
std::string studio;
public:
CD(const std::string &sname,double sprice, const std::string &sartist, const std::string &sstudio)
: Products ("CD", sprice, sname)
{
artist = sartist;
studio = sstudio;
}
void show() const override
{
Products::show(); // Call parent show() to show the basics
std::cout<<"\nArtist of the " << gettype() << ":\t"<<this->artist;
std::cout<<"\nStudio of the " << gettype() << ":\t"<<this->studio;
}
};
int main()
{
Products shoe ("Shoe", 3.49, "Nike runner");
shoe.show();
CD obj("Oceans",49,"somesinger","somestudio");
obj.show();
}
I have read Head First Design Pattern recently. The book shows related codes in Java. However, I try to convert Java codes to C++. At Observer pattern chapter, I got stuck while converting somewhere. Related codes are follows.
class Subject{ //Publisher
public:
virtual void registerObserver(ObserverPtr o) = 0;
virtual void removeObserver(ObserverPtr o) = 0;
virtual void notifyObservers() = 0;
};
using SubjectPtr = std::shared_ptr<Subject>;
Subscriber class interface:
class Observer{
public:
virtual void update(double temp, double humidity, double pressure) = 0;
};
using ObserverPtr = std::shared_ptr<Observer>;
Display Element interface:
class DisplayElement{
public:
virtual void display() = 0;
};
using DisplayElementPtr = std::shared_ptr<DisplayElement>;
and CurrentConditionsDisplay
class CurrentConditionsDisplay : public Observer, public DisplayElement{
SubjectPtr m_weatherData;
double temperature;
double humidity;
public:
CurrentConditionsDisplay(SubjectPtr weatherData);
void update(double temperature, double humidity, double pressure);
void display();
};
using CurrentConditionsDisplayPtr = std::shared_ptr<CurrentConditionsDisplay>;
My question:
At constructor of class CurrentCurrentConditionsDisplay, I would like that Publisher(Subject) registers CurrentCurrentConditionsDisplay.
//constructor
CurrentConditionsDisplay::CurrentConditionsDisplay(SubjectPtr weatherData) :
temperature(0),
humidity(0)
{
m_weatherData = weatherData;
/* How should I pass 'this' ? */
m_weatherData->registerObserver(???????); //parameter type is ObserverPtr.
}
How should 'pointer this' is passed due to the fact that parameter type is ObserverPtr?
I suggest factory method, something like:
std::shared_ptr<CurrentConditionsDisplay>
MakeCurrentConditionsDisplay(SubjectPtr weatherData)
{
auto res = std::make_shared<CurrentConditionsDisplay>(weatherData);
weatherData->registerObserver(res);
return res;
}
If you insist on doing it in the constructor, you might use std::enable_shared_from_this:
class CurrentConditionsDisplay :
public std::enable_shared_from_this<CurrentConditionsDisplay>,
public Observer,
public DisplayElement
{
SubjectPtr m_weatherData;
double temperature = 0;
double humidity = 0;
public:
explicit CurrentConditionsDisplay(SubjectPtr weatherData) :
m_weatherData(weatherData)
{
m_weatherData->registerObserver(shared_from_this());
}
void update(double temperature, double humidity, double pressure) override;
void display() override;
};
std::shared_from_this cannot be called called from constructor
I'm experimenting with the decorator design pattern in c++. However, I was not able to implement it without an abstract super-class from which both the core and decorating classes inherit.
I don't understand why abstract super-class is needed.
My working decorator example:
#include <string>
#include <iostream>
using namespace std;
// abstract superclass
class Pizza
{
public:
virtual string GetDescription() = 0;
virtual int GetCost() = 0;
};
// base class that can be extended
class Margharita: public Pizza
{
private:
string description;
int cost;
public:
Margharita(string t, int c){description = t; cost = c;}
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};
// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};
int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Margharita("Margharita", 100));
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}
that gives the output: Margharita, Extra Cheese 120.
If I remove the abstract super-class, the decoration stops working:
#include <string>
#include <iostream>
using namespace std;
// base class that can be extended
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
string GetDescription(){return(description);}
int GetCost(){return(cost);}
};
// decorator class that extends base class
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() { return(pizza->GetCost() + 20); }
};
int main()
{
// create decorated object
Pizza* pizza = new ExtraCheese(new Pizza());
cout << pizza->GetDescription() << '\n';
cout << pizza->GetCost() << '\n';
}
In this case the output only shows the attributes of the core object (Pizza 100).
Why is this happening?
When you removed the abstract base class you made the function GetDescription and GetCost not virtual. As such they aren't dispatched dynamically. Which is why pizza->GetDescription() called the Pizza member function, it was a call resolved based on the static type of pizza only.
You don't need to have an abstract base to make it work again, only dynamic dispatch, so just add the virtual specifier
class Pizza
{
private:
string description;
int cost;
public:
Pizza(){description = "Pizza"; cost = 100;};
virtual string GetDescription(){return(description);}
virtual int GetCost(){return(cost);}
};
This will allow overriding in ExtraCheese, to be picked up by dynamic dispatch. You can also help the compiler catch such mistakes by employing the override specifier. Had you defined ExtraCheese like this:
class ExtraCheese: public Pizza
{
private:
Pizza* pizza;
public:
// constructor
ExtraCheese(Pizza* p) {pizza = p;}
string GetDescription() override { return (pizza->GetDescription() + ", Extra Cheese"); }
int GetCost() override { return(pizza->GetCost() + 20); }
};
A modern compiler would have complained you are trying to override a function that isn't declared virtual. The mistake would have been apparent.
I have a problem with this code when I tried to create an instance of this class, an error appears to be
not allowed to use the abstracted class "SavingAccount"
I don't know what can I do. I followed the steps given by edx Microsoft Intermediate C++.
BankAccount.h
#pragma once
#include <string>
class BankAccount
{
protected:
double balance;
public:
BankAccount(double initialBanlance);
virtual ~BankAccount();
double getBalance() const;
virtual void deposit(double amount);
virtual void withdraw(double amount);
virtual std::string getTermAndConditions() = 0;
virtual double getGuaranteeLimit() = 0;};
BankAccount.cpp
#include "BankAccount.h"
BankAccount::BankAccount(double initialBanlance)
:balance(initialBanlance)
{}
BankAccount::~BankAccount()
{}
double BankAccount::getBalance() const
{return balance;}
void BankAccount::deposit(double amount)
{
balance += amount;
}
void BankAccount::withdraw(double amount)
{balance -= amount;}
Freezable.h
#pragma once
//Pure virtual class ,representing the "freeable" capability
class Freezable {
public:
virtual void freeze()=0;
virtual void unfreeze()=0;
};
Loggable.h
#pragma once
#include <string>
//Pure virtual class, representing the "loggable"'
class loggable{
public:
virtual void log(const std::string& message)const = 0;};
SavingAccount.h
#pragma once
#include "BankAccount.h"
#include "Freezable.h"
#include "Loggable.h"
#include <list>
class SavingAccount :public BankAccount, public Freezable, public loggable
{
private:
double interestRate;
bool frozen;
public:
SavingAccount(double initialBalance, double interestRate = 0.0);
virtual ~SavingAccount();
void earnInterest();
virtual void deposit(double amount);
virtual void withdraw(double amount);
//implement pure virtual function from BankAccount class.
virtual std::string getTermAndConditions();
virtual double getGuarranteeLimit();
//Implement pure virtual from Freezable
virtual void freeze();
virtual void unfreeze();
//Implement pure virtual from Loggable class
virtual void log(const std::string & message)const;
};
SavingAccount.cpp
#include "SavingAccount.h"
#include <iostream>
SavingAccount::SavingAccount(double initialBalance, double interestRate)
:BankAccount(initialBalance), interestRate(interestRate), frozen(false)
{}
SavingAccount::~SavingAccount() {}
void SavingAccount::earnInterest()
{
if (!frozen) {
double interest = balance * (interestRate / 100);
deposit(interest);
}
}
void SavingAccount::deposit(double amount) {
if (!frozen) {
BankAccount::deposit(amount);
log("Deposit:" + std::to_string(amount));
}
}
void SavingAccount::withdraw(double amount) {
if (!frozen && amount <= balance) {
BankAccount::withdraw(amount);
log("withdrwal:" + std::to_string(amount));
}
}
std::string SavingAccount::getTermAndConditions() {
return "This is a savings account, You cannot go overdrawn.You earn interest.";
}
double SavingAccount::getGuarranteeLimit() { return 1000000; }
void SavingAccount::freeze() { frozen = true; }
void SavingAccount::unfreeze() { frozen = false; }
void SavingAccount::log(const std::string & message) const
{ std::cout << message << std::endl; }
You have a typo. The base class BankAccount is a pure abstract class, which has a virtual member function called
virtual double getGuaranteeLimit() = 0;
^^
and in your SavingAccount class(which is derived) you have implemented
virtual double getGuarranteeLimit();
^^
which is not same as base class. Hence, you never override the function in your derived class.
That is why you need to practice with override specifier which will produce a compiler error if no matching function is found in base class.
See, for example, compiling with Clag 7.0 clearly gives a compiler error:
prog.cc:76:17: error: 'getGuarranteeLimit' marked 'override' but does not override any member functions
virtual double getGuarranteeLimit()override;
#include <iostream>
#include <string>
using namespace std;
class Employee
{
public :
virtual int calculateSalary()= 0;
virtual string getName()=0;
virtual string getEngineer()=0; //error
virtual string getManager()=0; /error
virtual string getDirector()=0; /error
};
class Engineer: public Employee
{
protected:
string name;
int salary;
public:
Engineer(string n,int s):name(n),salary(s){ cout<<endl<<"Engineer Created"; }
~Engineer(){cout<<endl<<"engineer destroyed";}
int calculateSalary()
{
return salary * 2;
}
string getName()
{
return name;
}
string getEngineer()
{
return "Engineer";
}
};
class Manager:public Engineer
{
public:
Manager(string n,int s): Engineer(n,s) { cout<<endl<<"Manager Created"; }
~Manager(){cout<<endl<<"MANAGER destroyed";}
int calculateSalary()
{
return salary * 3;
}
string getName()
{
return name;
}
string getManager()
{
return "manager";
}
};
class Director:public Manager
{
public:
Director(string n,int s): Manager(n,s) { cout<<endl<<"Director Created"; }
~Director(){cout<<endl<<"Director destroyed";}
int calculateSalary()
{
return salary * 4;
}
string getName()
{
return name;
}
string getDirector()
{
return "director";
}
};
int main()
{
Engineer e1("rohit",20000),e2("soham",21000);
Manager m1("shyam",23000),m2("ram",23500);
Director d1("rahul",25000);
Employee *staff[] = {&e1,&e2,&m1,&m2,&d1};
for(int i=0;i<5;i++)
{
cout<<endl<<"Name : "<<staff[i]->getName() << "\t" << "Salary : " << staff[i]->calculateSalary();
}
cout<<endl<<staff[0]->getEngineer(); //error
cout<<endl<<staff[1]->getEngineer(); //error
cout<<endl<<staff[2]->getManager(); //error
cout<<endl<<staff[3]->getManager(); //error
cout<<endl<<staff[4]->getDirector(); //error
return 0;
}
/The lines with error are showing errors if i compile this code.
i want to know if it is possible to access the getEngineer(),getManager(),getDirector() via the staff pointer.
If yes, then how?
If not, then why?
and is there any alternative to access those functions keeping the data type of staff as it is(i.e Employee) ?/
All derived class from Employee must to implement all pure virtual methods, otherwise they cannot be instanced.
Why does this happen?
A derivative class inherits all methods (and member variables) from the base class.
In you case, base class has some pure virtual methods, and so the sub-classes (Engineer, Manager and Director) as well. A no-abstract class cannot have a pure virtual method, so in order to instantiate those classes, each of them should implement getEngineer() getManager() getDirector() methods.
What is the solution?
The problem in your case is a bad design decision.
The base class should represent a uniform interface for all derivative classes.
That's why, the base class Employee should not have method like getEngineer() which is a more specific information.
IMO, a better design decision (just looking at your code) could be:
class Employee {
public :
virtual int calculateSalary() = 0;
virtual string getName() = 0;
virtual string getTypeWork() = 0;
};
In that way (exploiting polymorphism property) each derivative class can correctly return a string representing its role job.
it is possible to access the getEngineer(),getManager(),getDirector() via the staff pointer. If yes, then how?
Yes, you can. However, as #Biagio Festa said you can't have pure virtual functions in your base class Employee without implementing them in your derived ones. So one solution could be having default implementations for those functions in your base class
class Employee
{
public :
virtual int calculateSalary()= 0;
virtual string getName()=0;
virtual string getEngineer() { return std::string(); }
virtual string getManager() { return std::string(); }
virtual string getDirector() { return std::string(); }
};
Then, you can override those functions in your derived classes only when needed like you did in your example.