繁体   English   中英

引发异常:读取访问冲突[C ++]

[英]Exception thrown: read access violation [C++]

你好 我目前正在学习编程,因此暂时不清理代码,我需要帮助来使代码首先运行。 另外,我对大量的代码块表示歉意。 我不知道这是否与问题无关,所以无论如何我都将其发布了。

我们当前的课程是在课堂上,我正在尝试让2个向导互相对决。 但是在此之前,我需要为两个向导的属性分配值:

class Spell
{
public:
    string name;
    unsigned int cost;
    unsigned int dmg;
};

class Wizard
{
public:
    string name;
    unsigned int hp;
    unsigned int mp;
    Spell* spell;
};


void assignWizardValues(Wizard* wizard, Spell* spell)
{
    wizard->hp = rand() % 25 + 76;
    wizard->mp = rand() % 25 + 76;
    spell->name = "Fireball";
    spell->cost = rand() % 10 + 6;
    spell->dmg = rand() % 10 + 6;
}

在我的main()中,我有这个:

int main()
{
    Wizard* wiz1 = new Wizard();
    Wizard* wiz2 = new Wizard();
    Spell* fireball1 = new Spell();
    Spell* fireball2 = new Spell();

    //Assign Property Values
    srand(time(NULL)); 

    cout << "Who is the first wizard?  ";
    cin >> wiz1->name;
    assignWizardValues(wiz1, fireball1);

    cout << "Who is the second Wizard?  ";
    cin >> wiz2->name;
    assignWizardValues(wiz2, fireball2);

    //Battle START!!

    while (canGoOn(wiz1) == true && canGoOn(wiz2) == true)
    {
        castSpell(wiz1, wiz2);
        castSpell(wiz2, wiz1);
    }

    system("pause");
    return 0;
}

为两个向导和两个咒语分配值都可以。 然后,当它进入战斗循环时,会弹出此错误:

Exception thrown: read access violation.
std::_String_alloc<std::_String_base_types<char,std::allocator<char> > 
>::_Get_data(...) returned nullptr.

这就是我目前所处的位置。 作为参考,这是我在该循环中可以使用的其他两个函数:

void castSpell(Wizard* caster, Wizard* enemy)
{
    cout << caster->spell->name << endl;
    caster->mp -= caster->spell->cost;
    enemy->hp -= caster->spell->dmg;
    cout << caster->hp << endl << caster->mp << endl << endl;
    cout << enemy->hp << endl << enemy->mp << endl << endl;
    cout << endl << endl;
}

bool canGoOn(Wizard* wizard)
{
    if (wizard->hp > 0 && wizard->mp > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

任何帮助将不胜感激,再次,我很抱歉代码转储,很抱歉代码不好,很抱歉,这篇文章很长。 我在绳子的尽头TbT

导致崩溃的问题是您没有在任何地方将法术分配给向导,因此指针默认初始化为空指针。 现在,您castSpellcastSpell函数中取消引用此空指针,以尝试访问无效的内存(未定义的行为)。

最好的是已经在构造函数中分配了该拼写,因此您永远不会陷入具有无效值的情况。 您可以通过多种方式来做到这一点:

Wizard(std::string name)
    : name(std::move(name)), // std::move: avoids unnecessary copying of data...
      hp(rand() % 25 + 76),
      mp(rand() % 25 + 76),
      spell(new Spell("Fireball"))
      // assuming Spell has a constructor similar to this one
{ }

变体:

Wizard
(
    std::string name, unsigned int hp, unsigned int mp,
    std::string spellName, unsigned int spellCost, unsigned int spellDamage
)
    : name(std::move(name)),
      hp(hp), mp(mp),
      spell(new Spell(std::move(spellName), spellCost, spellDamage))
      // same assumption...
{ }

现在,您可以定义所有已经在外部的参数,然后将它们传入(现在有许多参数,但是更具灵活性)。

好的,现在还有很多话要说:内存泄漏(您不删除使用new创建的对象),智能指针(让删除自动完成),移动语义(关于std::move含义是什么?)现在,您可能会忽略它……),封装(您的成员是公共的,应该是私有的),成员函数(以便您可以访问私有成员),内联与否以及隐藏实现细节(将代码拆分为标头)和来源),...

假设您刚开始学习时,稍后再进行所有操作(但是,如果有兴趣,请发表评论,我会发布更多内容...)。 只是样式问题:请勿将布尔值与true或false进行比较,只需直接使用条件即可:

while (canGoOn(wiz1) == true && canGoOn(wiz2) == false) // bad style
//                                               ^^^^^
// changed just for demonstration purposes!

while (canGoOn(wiz1) && !canGoOn(wiz2))  // the way to go.
//                      ^ to check if condition is NOT met...
//                        again for demonstration only, not in your REAL code!

与返回值类似,如果仍要计算布尔值,则直接将其返回:

bool canGoOn(Wizard* wizard)
{
    return wizard->hp > 0 && wizard->mp > 0; // just drop that if/else stuff around
}

这是我想到的。

当它们都在死亡前耗尽魔法时无限循环;)但是您可以修复它

#include<random>
std::random_device rd;  //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()

int ThrowDie(int dieSize)
{
    std::uniform_int_distribution<> dis(1, dieSize);
    return dis(gen);
}

#include <string>
#include <utility>
class Spell {
    const int cost_base;
    const int cost_die;
    const int damage_base;
    const int damage_die;
public:
    const std::string name;

    Spell(const std::string& name, int cost_base, int cost_die,
        int damage_base, int damage_die)
        : name(name), cost_base(cost_base), cost_die(cost_die)
        , damage_base(damage_base), damage_die(damage_die) {}
    virtual ~Spell() = default;
    // returns <cost, damage>
    std::pair<int, int> Cast();
};

std::pair<int, int> Spell::Cast()
{
    return std::make_pair(
        cost_base + ThrowDie(cost_die),
        damage_base + ThrowDie(damage_die)
    );
}

class Fireball : public Spell {
public:
    Fireball() : Spell("FireBall", 6, 10, 6, 10) {}
    using Spell::Cast;
};

class Wizard
{
public:
    Wizard(const std::string& name);
    void cast(Spell spell, Wizard& opponent);
    bool IsAlive();
private:
    const std::string name;
    int healthPoints;
    int manaPoints;
};

Wizard::Wizard(const std::string& name)
    : name(name)
{
    healthPoints = 76 + ThrowDie(25);
    manaPoints = 76 + ThrowDie(25);
}

#include <iostream>
void Wizard::cast(Spell spell, Wizard& opponent)
{
    auto reqEff = spell.Cast();
    if (reqEff.first > manaPoints)
    {
        std::cout << name << " does not have enough mana points to cast " << spell.name << "\n";
    }
    else
    {
        manaPoints -= reqEff.first;
        opponent.healthPoints -= reqEff.second;
        std::cout << name << " casts " << spell.name << ", which does "
            << reqEff.second << " damage to " << opponent.name <<"\n";
    }
}

bool Wizard::IsAlive()
{
    if (healthPoints > 0)
    {
        //std::cout << name << " is still alive!\n"; \\ a lot of text...
        return true;
    }
    std::cout << name << " is dead!" << std::endl;
    return false;
}

#include <iostream>
int main()
{
    std::string name;
    std::cout << "Name the first wizard: ";
    std::cin >> name;
    Wizard wiz1(name);
    std::cout << "Name the second wizard: ";
    std::cin >> name;
    Wizard wiz2(name);

    // Battle start
    while (wiz1.IsAlive() && wiz2.IsAlive()) {
        wiz1.cast(Fireball(), wiz2);
        wiz2.cast(Fireball(), wiz1);
    }

    std::cin.ignore();
}

输出示例:

Name the first wizard: HarryPotter
Name the second wizard: Voldemort
HarryPotter casts FireBall, which does 13 damage to Voldemort
Voldemort casts FireBall, which does 11 damage to HarryPotter
HarryPotter casts FireBall, which does 12 damage to Voldemort
Voldemort casts FireBall, which does 12 damage to HarryPotter
HarryPotter casts FireBall, which does 7 damage to Voldemort
Voldemort casts FireBall, which does 16 damage to HarryPotter
HarryPotter casts FireBall, which does 8 damage to Voldemort
Voldemort casts FireBall, which does 10 damage to HarryPotter
HarryPotter casts FireBall, which does 8 damage to Voldemort
Voldemort casts FireBall, which does 14 damage to HarryPotter
HarryPotter casts FireBall, which does 16 damage to Voldemort
Voldemort casts FireBall, which does 16 damage to HarryPotter
HarryPotter casts FireBall, which does 16 damage to Voldemort
Voldemort casts FireBall, which does 11 damage to HarryPotter
HarryPotter casts FireBall, which does 14 damage to Voldemort
Voldemort casts FireBall, which does 10 damage to HarryPotter
HarryPotter is dead!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM