Inherited overridden method not being called - c++

Why does the depositmoney() method within the operation method of the account class call the depositmoney() of the account class and not the one from the Sav_account class? The direct call to depositmoney() method calls method of the sub-class which is obvious. But can't understand why the indirect call from operations() does not give the expected result.
#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
int temp = 0;
class account
{
protected:
string name;
double balance;
int AccNo;
public:
void operations()
{
int r = 0;
do{
cout << "1.DEPOSIT" << endl;
cout << "2.WITHDRAW" << endl;
cout << "3.CHECK BALANCE" << endl;
cout << "0.EXIT" << endl;
cin >> r;
switch(r)
{
case 1:this->depositmoney();
break;
case 2:this->withdraw();
break;
case 3:this->displaybalance();
break;
case 0:cout << "Exiting" << endl;
break;
default:
break;
}
}
while(r != 0);
}
account(string Name, double bal)
{
name = Name;
balance = bal;
AccNo = temp++;
}
void displaybalance()
{
cout << "name :" << name << endl;
cout << "A/C" << AccNo << endl;
cout << "your balance is " << balance << endl;
}
void depositmoney()
{
float deposit;
cout << "enter deposit" << endl;
cin >> deposit;
balance += deposit;
}
protected:
void withdraw()
{
float withdrawal;
cout << "enter witdrawal amount" << endl;
cin >> withdrawal;
if(balance >= withdrawal)
{
balance -= withdrawal;
}
else
{
cout << "insufficient funds" << endl;
}
}
};
class Sav_account :public account
{
private:
double const CI = 5;
void depositinterest()
{
balance += balance*CI / 100;
}
public:
Sav_account(string Name, double bal) :account(Name, bal)
{
AccType = 0;
}
void depositmoney()
{
account::depositmoney();
depositinterest();
}
};
void main()
{
Sav_account *account1 = new Sav_account("Shaw", 50000);
account1->operations();// DEPOSIT RESULTS IN NO INTEREST
account1->displaybalance();
account1->depositmoney(); // **DEPOSIT FUNCTION OF Sav_account CALLS interest function**
account1->displaybalance();
_getch();
}

Your class is not polymorphic. You have no polymorphic functions and have not overridden anything. (You have hidden functions instead). As such, calling depositmoney(); from a function of account will call account::depositmoney().
To make a class polymorphic you need to use virtual functions. Any function that you want to have polymorphic behaviour needs to be declared as virtual in the base class, e.g. in account here:
virtual void depositmoney() {
In the derived class, since C++11, you can write:
void depositmoney() override
^^^^^^^^
which will cause a compiler error if you accidentally hide a function when you are trying to override it. (Although I'm guessing that you are using a compiler that doesn't support C++11, since most of those will also reject void main).
Also, any polymorphic base class should have a virtual destructor, i.e. virtual ~account() {} otherwise the code account *x = new Sav_account("Shaw", 50000); delete x; would cause undefined behaviour.
void main is illegal, main must have a return type of int.

There aren't any overridden methods in your classes; you haven't made any of them virtual.

Related

Cannot instantiate abstract class, but double checked overriding of virtual functions

I'm doing self-study C++. I tried a program from the book, that would normally allocate a few objects of two derived classes dynamically using an array of pointers. I'm however preparing for an assignment where I'm not allowed to use pointers, so I made an alternative version without pointers.
The only error it gives me is C2259 "cannot instantiate abstract class", but I'm pretty sure I have overriden all the virtual functions.
Here is the header:
#ifndef ACCTBAC_H_
#define ACCTBAC_H_
#include <iostream>
#include <string>
// Abstract Base Class
class 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;
public:
AcctABC(const std::string& s = "Nullbody", long an = -1, double bal = 0.0);
void Deposit(double amt);
virtual void Withdraw(double amt) = 0; // pure virtual function
double Balance() const { return balance; };
virtual void ViewAcct() const = 0; // pure virtual function
virtual ~AcctABC() {}
};
// Brass Account Class
class Brass : public AcctABC
{
public:
Brass(const std::string& s = "Nullbody", long an = -1, double bal = 0.0) : AcctABC(s, an, bal) {}
virtual void Withdraw(double amt);
virtual void ViewAcct() const;
virtual ~Brass() {}
};
// Brass Plus Account Class
class BrassPlus : public AcctABC
{
private:
double maxLoan;
double rate;
double owesBank;
public:
BrassPlus(const std::string& s = "Nullbody", 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;
virtual void Withdraw(double amt);
void ResetMax(double m) { maxLoan = m; }
void ResetRate(double r) { rate = r; }
void ResetOwes() { owesBank = 0; }
};
#endif
the class functions:
// acctabc.cpp -- bank account class methods
#include <iostream>
#include "acctabc.h"
using std::cout;
using std::ios_base;
using std::string;
// Abstract Base Class
AcctABC::AcctABC(const string& s, long an, double bal)
{
fullName = s;
acctNum = an;
balance = bal;
}
void AcctABC::Deposit(double amt)
{
if (amt < 0)
cout << "Negative deposit not allowed; "
<< "deposit is cancelled.\n";
else
balance += amt;
}
void AcctABC::Withdraw(double amt)
{
balance -= amt;
}
// protected methods for formatting
AcctABC::Formatting AcctABC::SetFormat() const
{
// set up ###.## format
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);
}
// Brass methods
void Brass::Withdraw(double amt)
{
if (amt < 0)
cout << "Withdrawal amount must be positive; "
<< "withdrawal cancelled.\n";
else if (amt <= Balance())
AcctABC::Withdraw(amt);
else
cout << "Withdrawal amount of $" << amt
<< " exceeds your balance.\n"
<< "Withdrawal cancelled.\n";
}
void Brass::ViewAcct() const
{
Formatting f = SetFormat();
cout << "Brass Client: " << FullName() << "\n";
cout << "Account Number: " << AcctNum() << "\n";
cout << "Balance: $" << Balance() << "\n";
Restore(f);
}
// BrassPlus methods
BrassPlus::BrassPlus(const string& s, long an, double bal, double ml, double r) : AcctABC(s, an, bal)
{
maxLoan = ml;
owesBank = 0.0;
rate = r;
}
void BrassPlus::ViewAcct() const
{
Formatting f = SetFormat();
cout << "BrassPlus Client: " << FullName() << "\n";
cout << "Account Number: " << AcctNum() << "\n";
cout << "Balance: $" << Balance() << "\n";
cout << "Maximum loan: $" << maxLoan << "\n";
cout << "Owed to bank: $" << owesBank << "\n";
cout.precision(3);
cout << "Loan Rate: " << 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 << "Bank Advance: $" << advance << "\n";
cout << "Finance charge: $" << advance * rate << "\n";
Deposit(advance);
AcctABC::Withdraw(amt);
}
else
cout << "Credit limit exceeded. Transaction cancelled.\n";
Restore(f);
}
and the main program:
// usebrass3.cpp -- polymorphic example using an abstract base class
#include <iostream>
#include <string>
#include "acctabc.h"
#include <vector>
const int CLIENTS = 4;
int main()
{
using std::cin;
using std::cout;
using std::vector;
using std::string;
vector<AcctABC> accounts(CLIENTS);
string temp;
long tempnum;
double tempbal;
char kind;
for (int i = 0; i < CLIENTS; i++)
{
cout << "Enter client's name: ";
getline(cin, temp);
cout << "Enter client's account number: ";
cin >> tempnum;
cout << "Enter opening balance: $";
cin >> tempbal;
cout << "Enter 1 for Brass Account: ";
while (cin >> kind && (kind != '1' && kind != '2'))
cout << "Enter either 1 or 2: ";
if (kind == 1)
accounts.push_back(Brass(temp, tempnum, tempbal));
else
{
double tmax, trate;
cout << "Enter the overdraft limit: $";
cin >> tmax;
cout << "Enter the interest rate "
<< "as a decimal fraction: ";
cin >> trate;
accounts.push_back(BrassPlus(temp, tempnum, tempbal, tmax, trate));
}
while (cin.get() != '\n')
continue;
}
cout << "\n";
for (int i = 0; i < CLIENTS; i++)
{
accounts[i].ViewAcct();
cout << "\n";
}
cout << "Done.\n";
return 0;
}
Here:
vector<AcctABC> accounts(CLIENTS);
you are trying to create a vector of AcctABC with CLIENTS default constructed AcctABC elements. But you cannot have AcctABC elements when the class is abstract. You also cannot have Brass elements in a vector of AcctABCs. You need pointers when you want to store a polymorphic type in a vector.
You cannot do this
vector<AcctABC> accounts(CLIENTS);
because it will make CLIENTS number of default constructed abstract base classes. You will also lose polymorphism and induce object slicing. Instead
vector<std::unique_ptr<AcctABC>> accounts;
then for example
accounts.push_back(std::make_unique<Brass>(temp, tempnum, tempbal));

How to change variable stored in parent class from an inherited class in C++

So as the title suggests I am attempting to change the number variable, originally stored as 1000. Change this variable in another class function, and then replace the original value (1000) with the newly updated number. I haven't been able to find anything online to help me with this.
I have tried using pointers to no avail.
#include <iostream>
using namespace std;
class data {
protected:
int number = 1000;
};
class fetchData : public data {
public:
int getNumber() {
return number;
}
int updateNumber(int newNumber) {
number = newNumber;
return number;
}
};
class function : public fetchData {
public:
void minusNumber(int numberTakeAway) {
int newNumber = number - numberTakeAway;
updateNumber(newNumber);
cout << "Taken away: " << numberTakeAway << endl;
cout << "\nShould be new number: " << number << endl; // Not updating parent class variable
}
};
void printData() {
fetchData r;
cout << "number: " << r.getNumber() << endl;
}
void minusNumber() {
function r;
r.minusNumber(200);
}
int main(void) {
fetchData q;
cout << "\nOriginal ";
printData();
cout << "\n";
minusNumber();
cout << "\nActual ";
printData();
cout << "\n";
return 0;
}
You seem to be confusing between static - class members, and non static - instance members.
number is an instance member which means every instance will have its own number with its own value.
Each of your functions main, printData, and minusNumber creates its own instance of function or fetchData class, and there is no connection between them.
Try this code, where there is only one instance:
int main(void) {
function q;
cout << "\nOriginal ";
q.printData();
cout << "\n";
q.minusNumber(200);
cout << "\nActual ";
q.printData();
cout << "\n";
return 0;
}
What you have done in the free functions is to create a new instance of your class. If you want to do something with q that you instantiated in main, you have to pass it. Or use the member function in your class. So below, I've changed printData to take a reference to q. And instead of calling the free function minusNumber, I've called the member function of your class. I deleted the free function as it is not used.
#include <iostream>
class data {
protected:
int number = 1000;
};
class fetchData : public data {
public:
int getNumber() const {
return number;
}
int updateNumber(int newNumber) {
number = newNumber;
return number;
}
};
class function : public fetchData {
public:
void minusNumber(int numberTakeAway) {
int newNumber = number - numberTakeAway;
updateNumber(newNumber);
std::cout << "Taken away: " << numberTakeAway << std::endl;
std::cout << "\nShould be new number: " << number << std::endl; // Not updating parent class variable
}
};
void printData(const function& r) {
std::cout << "number: " << r.getNumber() << std::endl;
}
int main(void) {
function q;
std::cout << "\nOriginal ";
printData(q);
std::cout << "\n";
q.minusNumber(200);
std::cout << "\nActual ";
printData(q);
std::cout << "\n";
return 0;
}

Is it possible to create a constructor for a derived class?

I am trying to call all the virtual functions in the derived class and then define them outside as the saving class, however I am looks like I am not properly defined my constructor class and I cannot seem to fix it.
I am using the constructor from class accountInfo to store the virtual functions and the protected members and I want balance to update using saving(current_balance,current_interest);. However, I am sure I have a logical error somewhere but I cannot find it. I know I do not use the constructor accountInfo(double addBalance, double intRate); because I want to update the value of balance using the derived class not the parent class
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
class accountInfo{
public:
accountInfo();
accountInfo(double addBalance, double intRate);
virtual void deposit(double amount);
virtual void withdraw(double amount);
virtual double calcInt();
virtual double monthlyProc();
void virtual print();
~accountInfo();
protected:
double balance = 0;
int numDeposits = 0;
int numWithdraws = 0;
double annual_Interest = 0;
double monthlyServiceFee = 10;
bool status = false;
};
class saving: public accountInfo{
public:
saving(double addBalance, double intRate);
void print();
void withdraw(double amount);
void deposit(double amount);
double calcInt();
double monthlyProc();
};
void saving::deposit(double amount){ //how to call back the base function
if(balance >=25){
status = true;
balance +=amount;
numDeposits++;
}
else
status = false;
cout << "Balance is below 25" << endl;
}
accountInfo::accountInfo(){}
accountInfo::accountInfo(double addBalance, double intRate){
balance = addBalance;
annual_Interest = intRate;
}
saving::saving(double addBalance, double intRate){
balance = addBalance;
annual_Interest = intRate;
}
void saving::withdraw(double amount){
balance -= amount;
numWithdraws++;
}
double saving::calcInt(){
double monthlyRate = annual_Interest/12;
double monthlyInterest = balance * monthlyRate;
return balance + monthlyInterest;
}
double saving::monthlyProc(){ //how to call calcInt to delete the following
balance -= monthlyServiceFee;
numWithdraws = 0;
numDeposits = 0;
monthlyServiceFee = 0;
return balance;
}
void saving::print(){
cout <<"current balance " <<balance << endl;
cout << "Interest Rate "<<annual_Interest << endl;
cout << "number of deposits " << numDeposits << endl;
cout << "number of withdraws " << numWithdraws << endl;
cout << "monthlyServiceFee " << monthlyServiceFee << endl;
}
accountInfo::~accountInfo(){}
int main(){
double current_balance = 0;
double current_interest = 0;
double money, money0;
//accountInfo obj0;
accountInfo obj = accountInfo(100,100);
char option;
while(option != 'Q'){
cout << "Select action" << endl;
cin >> option;
option = toupper(option);
saving obj1(current_balance,current_interest);
switch(option){
case('A'):
{
cout << "Please input your balance and interest rate: " << endl;
cin >> current_balance;
cin >> current_interest;
obj1 = saving(current_balance,current_interest);
}
break;
case('D'):
cout << "Money to deposit" << endl;
cin >> money;
obj1.deposit(money);
break;
case('W'):
cout << "Money to withdraw" << endl;
cin >> money0;
obj1.withdraw(money0);
break;
case('P'):
obj1.print();
break;
case ('Q'):
option = 'Q';
break;
}
}
// cout << "the balance after interest is " <<obj.calcInt() << endl;
// cout << "money after the monthly services " << obj.monthlyProc() << endl;
return 0;
}
If you ever have a class:
class Base {
public:
Base();
};
and some other derived class:
class Derived : public Base{
public:
Derived();
};
The proper way to call a parent class' constructor is like this:
Derived::Derived() : Base() {
// Some implementation
}
So you call the constructor after a :. So in your case, it would probably look something like this:
saving::saving(double addBalance, double intRate) : accountInfo(addBalance, intRate) {
// Some implementation
}
This will call accountInfo()'s constructor when saving() is constructed.

Passing a class to a function, giving error

BankDatabase bank is the class object:
class BankDatabase
{
private:
Customer* customers[25];
Account *accounts[25];
int count;
public:
BankDatabase();
Account* getAccount(int accountNum);
Customer* getCustomer(int accountNum);
void display();
void createAccount();
};
class Customer //CUSTOMER CLASS
{
private:
string fullName;
int accountNumber;
string address;
int phoneNumber;
public:
Customer();
Customer(string name, int acc, string add, int phone);
int getAccountNum() const;
string getName() const;
string toString() const;
/*bool Customer::operator> (Customer* a);*/
};
class Account //ACCOUNT CLASS
{
protected:
int accountNumber;
int PIN;
double totalBalance;
public:
Account();
Account(int acc, int P, double bal);
bool validatePIN(int pin);
int getAccountNum() const;
double getTotalBalance() const;
virtual string toString() const;
void credit(double amount);
virtual bool debit(double amount);
/*bool Account::operator> (Account* a);*/
};
The function prototype is
void AccountAccess(class bank); //This might be error
which is before main. int main:
int main()
{
BankDatabase bank;
int decision;
bool goodInput;
bool isDone = false;
do
{
cout << "Welcome to the Bank of Cthulhu!" << endl;
cout << endl;
do
{
cout << "Please select an option from the main menu: " << endl;
cout << endl;
cout << "1) Create an account" << endl;
cout << "2) Access your account" << endl;
cout << "3) Exit" << endl;
cout << endl;
cin >> decision;
if (decision == 1)
{
//bank.createAccount(); this works
goodInput = true;
}
else if (decision == 2)
{
AccountAccess(bank);
goodInput = true;
}
else if (decision == 3)
{
isDone = true;
goodInput = true;
}
else
goodInput = false;
} while (!goodInput);
} while (!isDone);
return 0;
}
and the actual function I am putting bank into is
void AccountAccess(BankDatabase b)
{ //Function that allows the user to access their account
int accInput;
int pin;
bool goodInput;
do
{
cout << "Enter account number or press 1 to return to the main menu: ";
cin >> accInput;
if(b.getAccount(accInput) != 0)
{
goodInput = true;
break;
}
else if (accInput == 0)
{
cout << "Returning to main menu..." << endl;
cout << endl;
goodInput = true;
break;
}
else if (b.getAccount(accInput) == 0)
{
cout << "Account not found. Please try again." << endl;
goodInput = false;
}
} while (!goodInput);
return;
}
giving me the error "'void AccountAccess(bank)' cannot convert argument 1 from 'BankDatabase' to 'bank'
I have tried several variations, but I'm not sure how to fix this and I know it's something simple. Any help would be appreciated.
This is a mistake:
void AccountAccess(class bank); //This might be error
You have declared a function called AccountAccess whose argument should be an object of class bank.
It should be:
void AccountAccess(BankDatabase bank);
which declares a function called AccountAccess whose argument should be an object of class BankDatabase.
First, you don't have a copy constructor for BankDatabase.
The function AccountAccess is declared as passing the BankDatabase instance by value instead of by reference. Because of that, the compiler wants to pass a copy of the instance. To do that you need a copy constructor in your class, as in
BankDatabase(const BankDatabase& rhs);
Or you can simply declare and define the function AccountAccess with a reference parameter:
void AccountAccess(BankDatabase& bank);
...
void AccountAccess(BankDatabase& b)
{
....
That way no copying need be done and you'll more likely get what you're really after. But, I would also use the same parameter name in both places.

C++ Overloading input with abstract class

I am trying to build a "candy shop user interface" and I have 4 classes:
SweetItem class - abstract base class
Candy, Cookie, IceCream classes - derived from the base class virtually
Cookielida - derived from both cookie and ice cream classes
Now I have in the base class:
class SweetItem
{
public:
/*=====Builders & Destructor & = Operator=====*/
SweetItem();
SweetItem(const SweetItem&);
~SweetItem();
const SweetItem& operator=(const SweetItem&);
/*=====Input\Output operators=====*/
friend ostream& operator<<(ostream&, const SweetItem&);
friend istream& operator>>(istream&, SweetItem&);
/*=====Static members=====*/
static void NoSweets() { cout << num_sweets; }
static int get_num() { return num_sweets; }
/*=====Virtual Interface=====*/
virtual SweetItem* clone() const = 0;
virtual SweetItem* enter() = 0;
virtual void print() const = 0;
virtual int get_amount() const =0;
virtual float get_price() const = 0;
virtual String get_type() const = 0;
virtual float get_total() const = 0;
/*=====Cyber Function=====*/
void color(const int) const;
protected:
private:
static int num_sweets;
};
The input/output are calling virtual functions "enter()" and "print()":
ostream& operator<<(ostream& op, const SweetItem& input) {
if(&input)
input.print();
return op;
}
istream& operator>>(istream& ip, SweetItem& input) {
input.enter();
return ip;
}
When I try to use the "enter()" of the cookielida like this:
int main() {
SweetItem* temp = new Cookielida;
cin >> *temp;
cout << *temp << endl;
}
It prints a default object that i set up instead of the entered selection by user. This is the virtual implementation:
SweetItem* Cookielida::enter() {
String ct, it;
float cp, ip;
cout << "Please select from the available options: " << endl;
cout << "1) Butter cookies " << BUTTERP << "$ per unit" << endl;
cout << "2) Chocolate chip cookies " << CHIPP << "$ per unit" << endl;
cout << "3) Oreo cookies " << OREOP << "$ per unit" << endl;
int opt1;
opt1 = error(1, 3);
switch (opt1)
{
case BUTTER: ct = "Butter cookies";
cp = BUTTERP;
break;
case CHIP: ct = "Chocolate chip cookies";
cp = CHIPP;
break;
case OREO: ct = "Oreo cookies";
cp = OREOP;
break;
default:
break;
}
cout << "Please select from the available options: " << endl;
cout << "1) Vanilla icecream " << VANIP << "$ per unit" << endl;
cout << "2) Chocolate icecream " << CHOCP << "$ per unit" << endl;
cout << "3) Yogurt icecream " << YOGUP << "$ per unit" << endl;
int opt2;
opt2 = error(1, 3);
switch (opt2)
{
case VANI: it = "Vanilla icecream";
ip = VANIP;
break;
case CHOC: it = "Chocolate icecream";
ip = CHOCP;
break;
case YOGU: it = "Yogurt icecream";
ip = YOGUP;
break;
default:
break;
}
cout << "How many cookielidas do you want? " << endl;
int a;
a = error(0, MAXAMOUNT);
SweetItem* temp = new Cookielida(a, ip, cp, it, ct);
return temp;
}
I believe that the problem is that the temp cookielida created in the "enter()" function is destroyed instead of copied to the temp in the "main()".
Also these are the constructors:
Cookielida::Cookielida(int a=0, float ip=0, float cp=0, const String& it="", const String& ct="") :
IceCream(ICEA, ip, it), Cookie(COKA, cp, ct), amount(a), price((ip + cp * 2)*1.5), type(ct + " " + it)
{
}
Cookielida::Cookielida(const Cookielida& input) :
IceCream(ICEA, input.get_ip(), input.get_it()),
Cookie(COKA, input.get_cp(), input.get_ct()),
amount(input.amount), price(input.price), type(input.type)
{
}
This is the output:
The problem is in your enter() function. It doesn't change the object itself, but rather creates a new one which is returned via pointer. So when you call input.enter(); in your operator>> overload, the class input refers to is not varied -- and in fact, nothing happens as the pointer you return is not used at all.
As a workaround, you can do the following
Cookielida& Cookielida::enter() //better return the derived object in a covariant way,
//not the base class pointer
//you can still downcast it if required
{
//read in those many parameters
//then either set the class member variables "a, ip, cp, it, ct"
//directly (--the preferred way)
//or use this cheap alternative
operator=(Cookielida(a, ip, cp, it, ct));
return *this;
}
You just totaly missed the point in design of your Cookielida::enter function. It returns totaly new object and does not change the old one.
Putting it is inside operator>> is just a nonsense, you may actualy want to put it other way arround.
int main() {
SweetItem* temp = new Cookielida;
SweetItem* temp2 = temp->enter();
temp2->print();
delete temp;
delete temp2;
}