开发者

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 from const 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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜