新手网站故障问题C ++

时间:2010-12-01 01:02:16

标签: c++ segmentation-fault

我正在开展一个项目,在那里我可以创建银行账户并能够存款和取款。我要创建两个银行帐户和两个人 - 一个是堆栈,另一个是堆。我应该每次存入和取出两次,并获取余额打印名称和ID和帐号。目前,我得到了我认为是站点故障,读取或写入受保护的内存。我已经留下了我认为错误所在的地方的评论。我将不胜感激任何帮助。感谢。

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

3 个答案:

答案 0 :(得分:4)

不要在这里使用指针。让这些字符串和整数成为成员变量。对于特定问题 - 在默认构造函数中赋值之前没有分配任何内存。

做类似的事情:

class BankAccount {
private:
    double balance;
    int accountNumber;
public:
    BankAccount() :
        balance( 0.0 ),
        accountNumber( 0 ) {}

    // ...

编辑:

关于代码的更多要点:

  • 在构造函数中使用初始化列表而不是分配给成员变量 - 这避免了首先默认初始化成员然后分配给它们的两步过程
  • 基本多态类应具有virtual析构函数,因此可以通过指向base的指针正确销毁派生类的实例
  • 多态类型通常需要遵循the rule of three以避免slicing
  • 不要创建基类virtual的所有成员函数,只要那些希望派生类重写的那些
  • 在制作类型多态之前想一想 - 你真的有没有所有者的银行账户吗?也许这只是一个类型?
  • 制作访问者方法const,以便您可以从const实例
  • 获取信息
  • 检查错误(您确定不希望允许从零或负余额帐户提款)

答案 1 :(得分:0)

“不使用指针”有点强,但尼古拉的意思是成员变量不应该指向基类型而只是那些类型

即。在BankAccount中,balance应该只是double而不是double*对其他人来说是明智的

或让BankAccount()调用BankAccount(0.0, 0),因为它会为Person()分配正确的字段,但出乎意料的是,这不符合我在C ++中的想法,因为Karl Knechtel评论< / p>

答案 2 :(得分:0)

您正在取消引用未初始化的指针,如果您更改其位置,它仍会执行相同的操作。

你看,c ++(和c)使用指针作为内存的地址,如果你没有初始化,那么它们将指向内存中的任何地方,因此解除引用将导致访问冲突(可能是因为你不知道是你的指针指向)。

正确的方法是:

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
}

或者,如果你想在后面分配内存:

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

当然,如上所述,在您的情况下,最好使用普通变量而不是指针。你应该在使用它们之前阅读更多有关指针的内容,它们可能很痛苦(我想我代表99.999%的C和C ++程序员在这里发言,我们都在那里)。