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;
}

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

That means Account needs a constructor that takes no parameters.

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

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 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.

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.

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 errors

TestAccount.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

where's the code for TestAccount.cpp?

#include "SavingsAccount.hpp"

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

	return 0;
}

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

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.

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?

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.

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.

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.

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.

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

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.

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";
}
		}

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.

I tried using void becuase using cout like you did in your suggestion but i get these errors:

TestAccount.cpp(36) : error C2563: mismatch in formal parameter list
TestAccount.cpp(36) : error C2568: '<<' : unable to resolve function overload D:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\ostream(974): could be 'std::basic_ostream<_Elem,_Traits> &std::endl(std::basic_ostream<_Elem,_Traits> &)'
with
[
_Elem=wchar_t,
_Traits=std::char_traits<wchar_t>
]
D:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\ostream(966): or 'std::basic_ostream<_Elem,_Traits> &std::endl(std::basic_ostream<_Elem,_Traits> &)'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
D:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\ostream(940): or 'std::basic_ostream<_Elem,_Traits> &std::endl(std::basic_ostream<_Elem,_Traits> &)'

Also can you tell me how I get 2 derived classes to use the same base class without the compiler complaining.

I found an example like this but i don't think it is right

#ifndef Account.hpp
#define Account.hpp
#include "Account.hpp"
#endif

and errors

d:\program files\microsoft visual studio 9.0\vc\SavingsAccount.hpp(1) : warning C4067: unexpected tokens following preprocessor directive - expected a newline
d:\program files\microsoft visual studio 9.0\vc\SavingsAccount.hpp(2) : error C2008: '.' : unexpected in macro definition
d:\program files\microsoft visual studio 9.0\vc\CheckingAccount.hpp(1) : warning C4067: unexpected tokens following preprocessor directive - expected a newline

I have a derived class very similar to savingsaccount which has the same functions as account but i overide them to charge a fee instead of give interest.

class a{};
class b: public a{};
class c: public a{};

The very short example lol

I suspect your problem with multiple inheritance is actually a multiple-include problem.

If you put Freaky_Chris's example in one file, you have no problem.

If you put all 3 classes into separate files that don't include each other, no problem. If the file for b includes a and the file for c includes a and your main includes both b and c, your main sees the following unless you protect from it:

class a{};
class b: public a{};
class a{};
class c: public a{};

The compiler then complains about a being defined twice.

The code sample you posted is similar to the portable way to prevent multiple inclusion. In each of your include files that need to be protected, add the 'wrapper'. The wrapper changes depending on the name of the include file. So in Account.hpp it would be:

#ifndef Account.hpp
#define Account.hpp
// The rest of what you currently have in Account.hpp goes here
#endif

This causes the contents of the file to be parsed only once. The second time the compiler 'sees' the file the symbol is defined and it skips to the endif.

For SavingsAccount.hpp the wrapper would look like:

#ifndef SavingsAccount.hpp
#define SavingsAccount.hpp
// The rest of what you currently have in SavingsAccount.hpp goes here
#endif

In some older code I used to work on, we used _ characters on the symbols, so the symbol for Fruit.hpp would be something like _Fruit_hpp_

The actual symbol you use in each file doesn't really matter, but it needs to be unique to the file. It would be bad if say Account.hpp and SavingsAccount.hpp used the same symbol in the ifdef and define. As soon as you included one, the other would be skipped and that is NOT the effect we're looking for.

Go ahead and put the headers in Account.hpp, SavingsAccount.hpp and CheckingAccount.hpp as it would be good practice to get used to doing it for class definition header files. (The only one you REALLY need right now is Account.hpp, but I would do all 3.)

(The sample you had was actually for protecting a 3rd-party file from multiple inclusion, where you didn't want to actually change their file, either because you couldn't or because it might get updated later.)


The two compiler errors you have related to streams are because the compiler can't figure out which version of the stream you want. It thinks it could use either the 'char' or the 'wchar_t' version of the stream, you may need to help it decide. Apparently it can't tell from your constant string.

Thanks Murtan and everyone......I did what you suggested and i changed the Account.hpp to Account_h which works (didn't work with account.hpp)

DO you know why i can't get the debit fnction to work like i mentioned in my previous post?

If i use void i get loads of errors but can i used double and return the cout?

This is one error

TestAccount.cpp(36) : error C2563: mismatch in formal parameter list TestAccount.cpp(36) : error C2568: '<<' : unable to resolve function overload
D:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\ostream(974): could be 'std::basic_ostream<_Elem,_Traits> &std::endl(std::basic_ostream<_Elem,_Traits> &)'
with
[
_Elem=wchar_t,
_Traits=std::char_traits<wchar_t>
]

I pass the function a double value but if the enter less than zero an error message is suppsed to be output

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'm not sure why you're getting the stream errors, I'm using Visual C++ Express and I'm not seeing the compile errors.

Are you mixing options for char and wchar_t somewhere?

I don't think so....

I've attached all my files but it's only what you've seen already.

Don't worry, i fixed it and it works how it should very gratefull to everyone who helped :D

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.