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;
Related
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.
Here I am trying to pass the instance of ATMMachine using "this" keyword to the HasCard class and trying to call any method of ATMMachine from HasClass using that instance. But I am not able to call any of the methods of ATMMachine.
For example unable to call machine->insertCard();
Could someone please help me to find out where the problem is?
Is there any better approach in CPP to communicate between classes?
class ATMState{
virtual void insertCard() = 0;
virtual void ejectCard() = 0;
virtual void insertPin(int pinNumber) = 0;
virtual void withdrawCash(int amount) = 0;
};
class ATMMachine;
class HasCard: public ATMState {
private:
ATMMachine* machine;
public:
HasCard(ATMMachine* _machine) {
machine = _machine;
machine->insertCard();
}
void insertCard() {
}
void ejectCard() {
}
void insertPin(int pinNumber) {
}
void withdrawCash(int amount) {
}
};
class ATMMachine{
public:
int balance;
ATMState* currentState;
ATMState* hasCard;
ATMState* noCard;
ATMState* hasPin;
ATMState* noCash;
ATMMachine() {
hasCard = new HasCard(this);
// noCard = new NoCard();
// noCash = new NoCash();
// hasPin = new HasPin();
currentState = hasCard;
}
void insertCard() {
cout<<"Card has been inserted" <<endl;
}
void ejectCard() {
}
void insertPin(int pinNumber) {
}
void withdrawCash(int amount) {
}
};
But I am not able to call any of the methods of ATMMachine. with the forward declaration class ATMMachine; you only tell that this class exists, but the compiler does not know anything of its member functions until the full class definition is reached.
That's why you get an error like this:
invalid use of incomplete type 'class ATMMachine'
machine->insertCard();
note: forward declaration of 'class ATMMachine'
class ATMMachine;
If you have this kind of cross dependencies you need to split the declaration of the member functions, constructors, or destructors and their definitions.
class ATMState {
virtual void insertCard() = 0;
virtual void ejectCard() = 0;
virtual void insertPin(int pinNumber) = 0;
virtual void withdrawCash(int amount) = 0;
};
class ATMMachine;
class HasCard : public ATMState {
private:
ATMMachine *machine;
public:
// only declare the constructor here
HasCard(ATMMachine *_machine);
void insertCard() {}
void ejectCard() {}
void insertPin(int pinNumber) {}
void withdrawCash(int amount) {}
};
class ATMMachine {
public:
int balance;
ATMState *currentState;
ATMState *hasCard;
ATMState *noCard;
ATMState *hasPin;
ATMState *noCash;
ATMMachine() {
hasCard = new HasCard(this);
// noCard = new NoCard();
// noCash = new NoCash();
// hasPin = new HasPin();
currentState = hasCard;
}
void insertCard() { cout << "Card has been inserted" << endl; }
void ejectCard() {}
void insertPin(int pinNumber) {}
void withdrawCash(int amount) {}
};
// move the definition of the HasCard constructor after the declaration of ATMMachine
HasCard::HasCard(ATMMachine *_machine){
machine = _machine;
machine->insertCard();
}
Is there any better approach in CPP to communicate between classes? Having the need to do something like that is often an indication that you should restructure your code. There are various ways how to solve such issues each with their pros and cons. But that's something to ask on codereview.
I'm trying to practice "Observer Design Pattern". When I thought a abstract's pure virtual method has been override by it's derived class, a error occurred.
There is a observer which is an abstract class in a independent file:
#ifndef DESIGN_PATTERNS_OBSERVER_H
#define DESIGN_PATTERNS_OBSERVER_H
#include "subject.h"
class Subject;
class Observer{
protected:
Observer();
public:
virtual ~Observer();
virtual void update(Subject *the_changed_subject) = 0;
};
Observer::Observer() {}
Observer::~Observer() {}
#endif //DESIGN_PATTERNS_OBSERVER_H
Observer defined a pure virtual method "update" which overrides as follow:
#ifndef DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#define DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#include <iostream>
#include "observer.h"
#include "concrete_subject.h"
class ConcreteObserver : public Observer{
public:
void update(Subject *the_changed_subject) override {
auto cs = dynamic_cast<ConcreteSubject *>(the_changed_subject);
std::cout << "status changed to " << cs->get_status() << std::endl;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_OBSERVER_H
And also there is a subject which is an abstract class too.The error "pure virtual method called" happened in "notify" method where I had marked.
From debug, it seems "notify" uses Observer's "update" rather than ConcreteObserver's.
However,in main function the _observers should stored pointers of ConcreteObservers which override "update".
#ifndef DESIGN_PATTERNS_SUBJECT_H
#define DESIGN_PATTERNS_SUBJECT_H
#include <list>
#include "observer.h"
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
#endif //DESIGN_PATTERNS_SUBJECT_H
And it has a derived class "ConcreteSubject":
#ifndef DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#define DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#include "subject.h"
class ConcreteSubject : public Subject {
private:
int status;
public:
ConcreteSubject() {
status = 0;
}
void set_status(int s) {
this->status = s;
Subject::notify();
}
int get_status() {
return status;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_SUBJECT_H
The main function:
#include <iostream>
#include <vector>
#include "singleton.h"
#include "observer/concrete_subject.h"
#include "observer/concrete_observer.h"
void test2() {
ConcreteSubject concreteSubject;
std::vector<ConcreteObserver> observers;
for (int i = 0; i < 5; ++i) {
ConcreteObserver observer = ConcreteObserver();
concreteSubject.attach(&observer);
observers.push_back(observer);
}
concreteSubject.set_status(2);
}
int main() {
test2();
return 0;
}
As I mentioned before, the _observers of ConcreteSubject's super class Subject should stored pointers of ConcreteObservers which override "update" already.
I don't understand why Observer's "update" still called.
Here is another strange thing.I make a small test has almost the same relationship of classes I showed.But no error occured.
class ABaseA{
public:
virtual void do_some() = 0;
};
class MidA : public ABaseA{
public:
void do_some() override {
cout << "real do some" << endl;
}
};
class ABaseB{
private:
list<ABaseA*> *bases;
public:
ABaseB() {
bases = new list<ABaseA*>();
}
virtual ~ABaseB() = default;
virtual void add(ABaseA* item) {
bases->push_back(item);
}
virtual void do_active() {
for(ABaseA *p : *bases) {
p->do_some();
}
}
};
class MidB : public ABaseB{
public:
MidB() = default;
void active() {
ABaseB::do_active();
}
};
void test3() {
MidA midA;
MidB midB;
midB.add(&midA);
midB.active();
}
The only difference is this code is in one file.
In the file of Subject.h you should be transfer below code to Subject.cpp:
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
Also you should be add class Observer; in top of Subject.h
#include <list>
#include "Observer.h"
class Observer; //you should be add this line
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Given 3 classes.
class vehicle{
public:
void start();
}
class airplane: public vehicle{
void start();
void setRoute(route r);
void setAltitude(altitude a);
}
class boat: public vehicle{
void start();
void setRoute(route r);
}
Suppose we receive a parameter by command line that let us understand if we will manage an airplane or a boat.
Vehicle* v;
if (parameter == 1) {
v = new airplane();
v->setRoute(r);
v->setALtitude(a);
}
if (parameter != 1) {
v = new boat();
v->setRoute(r);
}
v->start();
Note that different methods are called for boat and airplane before start.
(Start is the only common method)
This code will not work because v doesn't contains methods setRoute/SetALtitude.
What's the correct way of implement this pattern?
You can easily do:
if(parameter != 1)
{
boat *b = new boat;
b->setRoute(r);
v = b;
}
and similar for airplane.
class __declspec(novtable) vehicle{
public:
virtual void start();
virtual void setRoute(route r) = 0;
virtual void setAltitude(altitude a) = 0;
};
class airplane: public vehicle{
virtual void start();
virtual void setRoute(route r);
virtual void setAltitude(altitude a);
};
class boat: public vehicle{
virtual void start();
virtual void setRoute(route r);
virtual void setAltitude(altitude a);
};
if I have the following code:
class A
{
public:
virtual void Yo();
}
class B : public A
{
public:
virtual void Yo() override;
}
Is there a way to force B to implement method Yo in A? Like an interface or more specifically (in this case) an abstract?
My full code is here:
BaseObject.h
#pragma once
namespace Game
{
namespace Model
{
namespace Graphic
{
class BaseObject
{
public:
int Width;
int Height;
float X;
float Y;
float Z;
virtual void SetUp() = 0;
virtual void Reset() = 0;
};
}
}
}
Player.cpp
#include "pch.h"
#include "Abstract\BaseObject.h"
using namespace Game::Model::Graphic;
class Player : public BaseObject
{
public:
Player();
~Player();
//virtual void SetUp();
//virtual void Reset() override;
};
in A make Yo pure virtual
virtual void Yo() = 0;
a complete example
#include <iostream>
struct A
{
virtual void Yo() = 0;
};
struct B : A
{
virtual void Yo() { std::cout << "I'm B\n"; }
};
int main()
{
B b;
b.Yo();
return (0);
}
if B doesn't implement Yo this will not compile.
The override keyword it's not needed in this case.
You have to take pointer of the base class to implement virtual functions in C++. This seems quite obvious. But i think we have missed that. The most basic example is given below.
#include <iostream>
using namespace std;
class base {
public:
virtual void vfunc() {
cout << "This is base's vfunc().\n";
}
};
class derived1 : public base {
public:
void vfunc() {
cout << "This is derived1's vfunc().\n";
}
};
int main()
{
base *p, b;
derived1 d1;
// point to base
p = &b;
p->vfunc(); // access base's vfunc()
// point to derived1
p = &d1;
p->vfunc(); // access derived1's vfunc()
return 0;
}