新手网站故障问题C++

发布于 2024-10-05 16:16:11 字数 2343 浏览 1 评论 0原文

我正在开发一个项目,我可以在其中创建银行帐户并能够存款和取款。我要创建两个银行帐户和两个人 - 一个在堆栈上,另一个在堆上。我应该存款和取款各两次,并获得余额打印姓名、身份证件和帐号。目前,我认为是站点故障,读取或写入受保护的内存。我已经对我认为错误所在的地方发表了评论。我将不胜感激任何帮助。谢谢。

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

睡美人的小仙女 2024-10-12 16:16:11

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

做类似的事情:

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

    // ...

编辑:

关于代码的更多要点:

  • 在构造函数中使用初始化列表而不是分配给成员变量 - 这避免了首先默认初始化成员然后分配给它们
  • 基多态类 的两步过程应该有虚拟析构函数,因此派生类的实例可以通过指向基本
  • 多态类型的指针正确销毁,通常需要遵循三法则以避免切片
  • 不会使基类的所有成员函数虚拟,仅使那些您希望派生类重写的成员函数
  • 在使类型多态之前思考 - 您真的拥有没有所有者的银行帐户吗?也许这只是一个类型?
  • 使访问器方法const,这样您就可以从const实例获取信息
  • 检查错误(您肯定不希望允许从零或负余额帐户提款)

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)
只涨不跌 2024-10-12 16:16:11

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

,即在 BankAccount 中,balance 应该对于其他人来说,只是一个 double 而不是 double*

,或者让 BankAccount() 调用 BankAccount(0.0, 0) 因为这将像 Person() 一样正确分配字段,但出乎意料的是,这并没有达到我在 C++ 中的预期,正如 Karl Knechtel 所说

"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

木落 2024-10-12 16:16:11

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

你看,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++ 程序员发言,我们都经历过)。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文