Newbie Site fault issue C++
I'm working on a project where I create bank accounts and able to deposit and withdraw. I am to create two bank account and two people- one one the stack and the other on the heap. I should deposit and withdraw into each twice and get the balance print the name and ID and account numbers. At the moment I'm get what I believe is a site fault , reading or writing to protected memory. I've left comments on where I think the errors lie. I would appreciate any help. Thanks.
#include <iostream>
#include <string>
using namespace std;
class BankAccount {
private:
double *balance;
int *accountNumber;
public:
BankAccount(){//default constructor
*balance = 0.0;/***This is where is says the Access violation lies*/
*accountNumber = 0;
}
BankAccount(double bal, int acctNum){//constructor
balance = new double(bal);
accountNumber = new int(acctNum);
}
~BankAccount() {delete balance; delete accountNumber;}
void Deposit(double amt) {
*balance = *balance + amt;
}
virtual double GetBalance() {
return *balance;
}
virtual double GetAccountNumber() {
return *accountNumber;
}
virtual double Withdraw(double amt) {
*balance = *balance - amt;
return *balance;
}
};
class Person {
string *name;
int *ID;
public:
Person(){//default constructor
开发者_JAVA技巧*name = "name not yet defined";
*ID = 0;
}
Person(string nameIn, int idIn){//constructor
name = new string(nameIn);
ID = new int(idIn);
}
virtual int GetID() {
return *ID;
}
virtual string GetName() {
return *name;
}
};
class NamedBankAccount: public BankAccount {
private:
Person *owner;
public:
NamedBankAccount(){
}
NamedBankAccount(Person *p): owner(p){/***This is where is says the Access violation lies*/
p = new Person();
}
~NamedBankAccount(){delete owner;}
Person getPerson() {
return *owner;
}
};
int main() {
Person *q = new Person("Joe", 54321);
cout << q->GetName() << endl;
cout << q->GetID() << endl;
NamedBankAccount nba1;/***This is where is says the Access violation lies*/
NamedBankAccount *nba2 = new NamedBankAccount(q);
nba1.Deposit(50);
nba1.Deposit(50);
nba1.Withdraw(25);
cout << nba1.GetBalance() <<endl;//should print 75
nba2->Deposit(60);
nba2->Deposit(60);
nba2->Withdraw(20);
cout << nba2->GetBalance() << endl;//should print 100
getchar();
return 0;
}
Do not use pointers here. Just have those strings and integers be member variables. For the specific problem - you haven't allocated any memory before assignment in the default constructor.
Do something like:
class BankAccount {
private:
double balance;
int accountNumber;
public:
BankAccount() :
balance( 0.0 ),
accountNumber( 0 ) {}
// ...
Edit:
Couple of more points about your code:
- make use of initialization list in the constructors instead of assignment to member variables - this avoids two-step process of first default-initializing the members and then assigning to them
- base polymorphic classes should have
virtual
destructors, so instances of derived classes could be properly destroyed via pointer to base - polymorphic types usually need to follow the rule of three to avoid slicing
- do not make all member functions of a base class
virtual
, only those you want derived classes to override - think before making a type polymorphic - do you really have bank accounts without owners? Maybe that can be just a value type?
- make accessor methods
const
, so you can get information fromconst
instances - check for errors (you sure don't want to allow withdrawals from zero or negative balance accounts)
"do not use pointers" is a bit strong but what Nikolai means is that member variables shouldn't be pointers to base types but just those types
i.e. in BankAccount
, balance
should just be an double
and not a double*
like wise for the others
or have BankAccount()
call BankAccount(0.0, 0)
as that will allocate the fields right like wise for Person()
but unexpectedly this doesn't do what i thought it would in C++ as Karl Knechtel remarks
You are dereferencing an uninitialized pointer, if you change their places it would still do the same thing.
You see, c++ (and c) uses pointers as addresses to memory, if you don't initialize then they will point to anywhere in memory, so dereferencing will PROBABLY cause access violation (probably because you don't know were your pointer points to).
The correct way would be:
BankAccount(){//default constructor
balance = new double; // Initialize pointer (make it points to a valid memory address)
*balance = 0.0; // Give a value to the variable where balance is pointing
accountNumber = new int; // Initialize pointer (make it points to a valid memory address)
*accountNumber = 0; // Give a value to the variable where balance is pointing
}
OR, if you want to allocate memory latter:
BankAccount(){//default constructor
balance = 0; // Make it point to address 0 (conventional value meaning it is uninitialized)
accountNumber = 0; // Make it point to address 0 (conventional value meaning it is uninitialized)
}
Of course, as stated, in your case it would probably be best to use normal variables and not pointers. You should read more about pointers before using them, they can be a pain (I think I speak here on behalf of 99.999% of C and C++ programmers, we've all been there).
精彩评论