954,504 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Inheritance errors

I have made a base class and a derived class and I am having a couple compile errors.

SavingsAccount.hpp(9) : error C2512: 'Account' : no appropiate default constructor available

What i want to do is be able to give the savings account an inital balance and it changes the currentBalance variable in the account class.

Base class

#include <iostream>
using namespace std;

class Account {

	friend class SavingsAccount;
	//friend class CheckingAccount;
	
	double deposit;
	//double withdrawal;

	public:
		Account(double newBalance) {//, double deposit, double withdrawal) {
			currentBalance = newBalance;
			//newBalance >= 0 ? currentBalance += newBalance : cout << "Initial balance invalid";
		};

		~Account() { };

		int getBalance() { return currentBalance; }	

		void credit() { currentBalance += deposit; }
	
		//void debit() { currentBalance >= withdrawal ? currentBalance -= withdrawal : cout << "Debit amount exceeded account balance"; }
	
	private:
		double currentBalance;

};


derived class

#include "Account.hpp"
#include <string>

class SavingsAccount : public Account {

	double Balance;
	
	public:
		SavingsAccount(double initBalance, double initInterestRate) {
			InterestRate = initInterestRate;
			Balance = initBalance;	
		};

		~SavingsAccount() { };

		void CalculateInterest(Account& ac, double InterestRate) {
			ac.getBalance *= InterestRate;
		};

	private:
		double InterestRate;

};


main program
#include "SavingsAccount.hpp"

int main() {
	
	Account account(75.00);
	SavingsAccount savings(100.00, 2.5);
	
	cout << "Current Balance:" << account.getBalance();

	return 0;
}
AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

>>SavingsAccount.hpp(9) : error C2512: 'Account' : no appropiate default constructor available

That means Account needs a constructor that takes no parameters.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

I did what you said and changed the constructor so it takes no values but i still get errors

TestAccount.cpp TestAccount.cpp(5) : error C2664: 'Account::Account(const Account &)' : cannot convert parameter 1 from 'double' to 'const Account &' Reason: cannot convert from 'double' to 'const Account' No constructor could take the source type, or constructooverload resolution was ambiguous

Also i need the constructor to take an initial value

AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

well when you create the object of the child class the base class ctor gets called and since you have declared your own ctor the compiler doesn't give you a default ctor. In the definition of the child class ctor you should pass the required value to the base class ctor.

something like

SavingsAccount(double initBalance, double initInterestRate):Account(initBalance) {
			InterestRate = initInterestRate;
			Balance = initBalance;	
		};
Agni
Practically a Master Poster
655 posts since Dec 2007
Reputation Points: 431
Solved Threads: 116
 

I did what you said and changed the constructor so it takes no values but i still get errors

Also i need the constructor to take an initial value

you can have as many constructors as you like.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

I was going to give you Agni's answer (lucky I saw it when I switched to Advanced).

Also, there is no requirement that a class have only one constructor.

You could actually declare both (not that you want to in this instance):

Account(double newBalance) {
	currentBalance = newBalance;
};
Account() {
	currentBalance = 0;
};


(Arg! I must type slow, Dragon said this already)

Design Comment:

I'm not overly fond of adding friends to a class (I do it when I need to, but try to avoid it when possible). You should not need to make derived classes a friend of the parent. If you have things that you want derived classes to be able to see / modify, make them protected instead of private, or provide protected accessors if that works better for you.

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

well when you create the object of the child class the base class ctor gets called and since you have declared your own ctor the compiler doesn't give you a default ctor. In the definition of the child class ctor you should pass the required value to the base class ctor.

something like

SavingsAccount(double initBalance, double initInterestRate):Account(initBalance) {
			InterestRate = initInterestRate;
			Balance = initBalance;	
		};


I did this but still get errorsTestAccount.cpp
SavingsAccount.hpp(9) : error C2664: 'Account::Account(const Account &)' : cannot convert parameter 1 from 'double' to 'const Account &'
Reason: cannot convert from 'double' to 'const Account'
No constructor could take the source type, or constructor overload resolution was ambiguous

TestAccount.cpp(5) : error C2664: 'Account::Account(const Account &)' : cannot convert parameter 1 from 'double' to 'const Account &'
Reason: cannot convert from 'double' to 'const Account'
No constructor could take the source type, or constructor overload resolution was ambiguous

AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

where's the code for TestAccount.cpp?

Agni
Practically a Master Poster
655 posts since Dec 2007
Reputation Points: 431
Solved Threads: 116
 
#include "SavingsAccount.hpp"

int main() {
	
	Account account(75.00);
	SavingsAccount savings(100.00, 2.5);
	
	cout << "Current Balance:" << account.getBalance();

	return 0;
}
AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

To use Agni's code, Account needs the Account(double newBalance) constructor.

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

Thanks that compiles now.

Just another quick question......

How do i give the variable currentBalance the value of newBalance?

I would normally put currentBalance = newBalance

I wouold have put that in the constructor but if i can't where do i put it. I would also need to check the value of the newBalance to make sure it's greater than 0 but i would presume that goes in the same place.

AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

I'm seeing a compile error in SavingsAccount:

void CalculateInterest(Account& ac, double InterestRate) {
			ac.getBalance *= InterestRate;
		};


Several comments / questions:

getBalance is a method of Account (that should return a double instead of an int) but you can't update a method.

Why does CalculateInterest take an account and an interest rate as parameters? It is a member of the SavingsAccount class and has access to the parent class account and the member variable InterestRate.

And every time I've seen it used, an interest calculation has a 'period' to which it applies. Is the stored interest rate in % / year? What period is CalculateInterest() supposed to calculate for?

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

currentBalance = newBalance is taken care of by calling Account(newBalance).

You could validate it in Account's constructor, but if the new balance is negative, there isn't much you can do about it.

You could exit the application or throw an exception, but if you don't handle the exception the application exits anyway, and exiting seems so unfriendly.

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

I noticed that earlier and i made the changes

#include "Account.hpp"
#include <string>

class SavingsAccount : public Account {

	double Balance;
	
	public:
		SavingsAccount(double initBalance, double initInterestRate):Account(initBalance) {
			InterestRate = initInterestRate;
			Balance = initBalance;	
		};

		~SavingsAccount() { };

		void CalculateInterest(Account& ac, double InterestRate) {
			ac.currentBalance *= InterestRate;
		};

	private:
		double InterestRate;

};


What it needs to do is get an initial balance and an iterest rate and multlply the initial balance by the interes rate to give an amount of interest. I also need to upate the current balance in the Account file.

AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

currentBalance = newBalance is taken care of by calling Account(newBalance).

You could validate it in Account's constructor, but if the new balance is negative, there isn't much you can do about it.

You could exit the application or throw an exception, but if you don't handle the exception the application exits anyway, and exiting seems so unfriendly.

How do i go about calling that? is it a seperate function?

What i want to do if the initial balance is a negative number is set the initial balance to 0 and give a warning message.

AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

Bank Accounts tend to be very transactional...

Maybe it should do something like:

// Doesn't need parameters, its for 'this' savings account at the 'current' interest rate
void CalculateMonthlyInterest() {
    credit( getBalance() * (InterestRate / 12) /*, "Interest Earned"*/);
};
// and account's credit would do something like:
void credit( double creditamt /*, char const * description */) {
    currentBalance += creditamt;
}


PS- your last posted calculate interest method REPLACED the balance with the interest.


For your proposed initial balance handling:

Accout(double newbalance) {
    if (newbalance < 0) {
        cout << "Invalid opening balance specified, using zero";
        newbalance = 0;
    }
    currentBalance = newbalance;
}


as to calling the constructor, you are calling it when your SavingsAccount constructor is called:

SavingsAccount(double initBalance, double initInterestRate):
    Account(initBalance) // this is the Account constructor
{
    InterestRate = initInterestRate;
};


You made SavingsAccount a friend of Account so it can modify the balance directly. What if it wasn't a friend? SavingsAccount could look at the balance with getBalance() and modify the balance through the credit and debit methods. That would give Account a lot more control of the balance to make sure that all of the 'proper' rules were followed.

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

Do you suggest not using friend and take it out?

I really appreciate all your help and am understanding it much better.

I think i've got it working now so just need to improve it...many thanks

AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

I suggested that children should never be a friend of their parent.

Parents should define anything the children should have access to in the protected: section.

I was also arguing that in this case, the balance should remain private and the child classes would use debit() and credit() to update the balance.

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

Thanks Murtan....I understand that.

The point you weere aruing about using debit and credit was exactly what i wanted to do and it works perfectly with the firends taken out and the currentbalance set to protected.

I can perform calculations on there like calculating interest, adding interest to to the balance and crediting the account but i'm stuck on the debit account. I don't know how i start the function because with void i got loads of errors but with double i have to return something but how do i have an error message in there if it's double?

this is on account.hpp

void debit(double withdrawal) {
    if(currentBalance >= withdrawal) {
        currentBalance -= withdrawal;
    }
    else {
        cout << "Debit amount exceeded account balance";
}
		}
AdRock
Junior Poster in Training
64 posts since Dec 2008
Reputation Points: 10
Solved Threads: 0
 

What errors are you seeing on that function, it looks like it should work.

Mine currently looks like:

void debit( double amount ) { 
    if (amount < 0) {
        cout << "Invalid debit amount (" << amount << "), debits must be >= 0" << endl;
    } else if (amount > currentBalance) {
        cout << "Debit amount (" << amount << ") exceeded account balance (" << currentBalance << ")" << endl;
    } else {
        currentBalance -= amount;
    }
}


I have not run test with the above code, but it does compile.

The last argument I was making was actually to keep the balance private and make the child classes use the member functions getBalance() to get the balance and debit() and credit() to update the balance.

The print statements about bad values are probably sufficient for this level of code, but normally, you wouldn't want to print that you had a problem, but to return an indication of a problem to the caller so they could decide how to handle it. This would allow the program to customize the response to the context in which it was encountered.

So if this were for a long-term project, a better prototype might be: int debit( double amount );

Where the method would return 0 for success and a non-zero error code to indicate a problem.

Murtan
Practically a Master Poster
671 posts since May 2008
Reputation Points: 344
Solved Threads: 116
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You