-1

我希望能够制作一个战斗场景并将其放入一个函数中,但每次我尝试时我都必须在不同的头文件中创建对象,然后我无法在 main.js 中调用它。为了解决这个问题,我在主函数中创建了循环,但它说调用该方法的对象必须是可修改的。

//main.cpp
int main()
{
    Characters h;//Created using normal constructor
    cout << "Character: \n";
    h.setAttack(5);
    h.getAttack();
    h.setDefense(15);
    h.getDefense();
    Hero Me;
    cout << "Hero: \n";
    Me.setAttack(10);
    Me.getAttack();
    Me.setHp(5);
    Me.getHp();
    Hero::Hero(1,2,3,4);//Created using overloaded constructor
    Monsters m;
    cout << "Monster: \n";
    m.setAttack(20);
    m.getAttack();
    Monsters::Monsters(5,6,7,8);

//Problem is this this loop! i cant access the member functions for my objects.
//And i want to be able to put this in a function and call it from another file!
do
{
    cout << "Attacking!\n";
    cout << "Your hp is: " << Me.getHp() << endl;
    cout << "The enemy's hp is: "<< m.getHp << endl;
    cout << "\nThe monster has attacked you!\n";
    cout << "You received " << m.getStrength() << " damage;" << endl;
    Me.setHp() -= m.getStrength() ;//It compiles an error, saying its not modifiable
    cout << "\nYour hp is now: " << Me.getHp() << endl;
    cout << "Enemy hp is: "<< m.getHp << endl;
    cout << "\nNow you attacked!\nYou have dealt "<< Me.getAttack() << " Damage" <<      endl;
    m.setHp() -= Me.getAttack();
    cout << "Enemy hp is now: " << m.getHp() - Me.getAttack() << endl;
}while ((Me.getHp() >= 0) && (m.getHp() >= 0));

    if ((Me.getHp > 0) && (m.getHp < 0))
 cout <<"Congratulations! You killed the enemy!" << endl;
 else if ((Me.getHp < 0) && (m.getHp > 0))
 cout << "You have died!" << endl;

 cin.sync();
 cin.get();
 return 0;
}



//Here's the rest of my code.

//Hero.h
class Hero:
    public Characters
{

public:
    Hero();
    Hero(int, int, int, int);
    ~Hero(void);

};


//Hero.cpp
int Herolevel;
int HeroHp;
int HeroStrength;
int HeroAttack;
int HeroDefense;

Hero::Hero()
{
    cout << "HOLA! Hero Created using normal constructor\n";
}

Hero::Hero(int newHp, int newLevel, int newAttack, int newDef)
{
    cout << "Hero created using Overloaded function!\n";
    HeroHp = newHp;
    cout << "Hp is: "<< HeroHp << endl;
    Herolevel = newLevel;
    cout << "level is: " << Herolevel << endl;
    HeroAttack = newAttack;
    cout << "Attack is: " << HeroAttack << endl;
    HeroDefense = newDef;
    cout << "Defense is: " << HeroDefense << endl;
}


Hero::~Hero(void)
{
    cout << "Hero destroyed!\n";
}


//Monsters.h
#pragma once
#include "Hero.h"
#include "Characters.h"
class Monsters:
    public Characters //Hero
{

public:
    Monsters(void);
    Monsters(int, int, int, int);
    //Monsters(int);
    ~Monsters(void);
};

//Monsters.cpp
int Monsterlevel;
int MonsterHp;
int MonsterStrength;
int MonsterAttack;
int MonsterDefense;

Monsters::Monsters(void)
{
    "Monster Created";
}

Monsters::Monsters(int newHp, int newLevel, int newAttack, int newDef)
{
    cout << "Monster created using Overloaded function!\n";
    MonsterHp = newHp;
    cout << "Hp is: "<< MonsterHp << endl;
    Monsterlevel = newLevel;
    cout << "level is: " << Monsterlevel << endl;
    MonsterAttack = newAttack;
    cout << "Attack is: " << MonsterAttack << endl;
    MonsterDefense = newDef;
    cout << "Defense is: " << MonsterDefense << endl;
}

Monsters::~Monsters(void)
{
    cout << "\nMonster Destroyed";
}


//Characters.h
#pragma once
class Characters
{
private:
    int level;
    int Hp;
    int Strength;
    int Attack;
    int Defense;
public:
    Characters(void);
    Characters(int);
    Characters(int, int, int, int);
    ~Characters(void);


    int getAttack();
    int getDefense();
    int getStrength();
    int getHp();
    int getLevel();

    void setAttack(int);
    void setDefense(int);
    void setStrength(int);
    void setHp(int);
    void setlevel(int);
};


//Characters.cpp
Characters::Characters(void)
{
    cout << "\nCharacter has been created!\n";

}

Characters::Characters(int random)//How can i make this work?
{
    cout << "Level " << level << " character created with: \n";
    /*srand ((unsigned)time(0));
    random = rand() % 10 + 1;
    setlevel(int random);*/
    level = random;

}

Characters::~Characters(void)
{
    cout << "Character has been destroyed!\n";
}

void Characters::setAttack(int att)//get Character left over hp
    {
        Attack = att;
    }

void Characters::setDefense(int def)//get Character left over hp
    {
        Defense = def;
    }

void Characters::setStrength(int str)//get Character left over hp
    {
        Strength = str;
    }

void Characters::setHp(int damage)//get Character left over hp
    {
        Hp -= damage;
    }

void Characters::setlevel(int lvl)//get Character left over hp
    {
        level = lvl;
    }


int Characters::getAttack()
{
    cout << "Your attack is: " << Attack << endl;
    return Attack;
}

int Characters::getDefense()
{
    cout << "Your defense is: " << Defense << endl;
    return Defense;
}

int Characters::getStrength()
{
    cout << "Your strength is: " << Strength << endl;
    return Strength;
}

int Characters::getHp()
{
    cout << "Your hp is: " << Hp << endl;
    return Hp;
}

int Characters::getLevel()
{
    cout << "Your level is: " << level << endl;
    return level;
}
4

2 回答 2

1

首先,不要将变量声明为全局变量,将它们声明为成员变量!当您声明一个全局变量时,您的程序中将只有该变量的一个实例,因此如果您创建(例如)两个Monster对象,则两者都将使用相同的全局变量。

除了一个,你也不会创造任何怪物m。第二次调用Monster构造函数时不会创建新Monster对象,只需调用其构造函数即可。使变量成为成员变量后(只需在类中声明它们),您可以像这样使用非默认构造函数:

Monster m;  // Uses default constructor
Monster m2(5, 6, 7, 8);  // Uses the other constructor

至于您遇到的问题,该getHp方法仅返回命中点的副本,因此该语句实际上并没有做任何事情(它修改了返回的副本,然后将其丢弃)。相反,您应该调用该setHp方法:

Me.setHp(Me.getHp() - m.getStrength());
于 2013-06-14T04:00:58.257 回答
0

您对 OOP(面向对象编程)和 C++ 编程的理解似乎存在脱节。

在 C++(和 C)中,您必须在使用之前声明所有内容。所以如果你有一个需要使用的类,你必须先声明它。否则你得到一个错误。

在 OOP 编程中,对象是定义的一个实例class。一个类有几个关键组件,但可能并非全部都存在:

  1. 有一个构造函数:

    这设置了任何新实例的初始状态,class并且通常分配对象使用的资源。

  2. 有一个析构函数:

    这将释放对象使用的资源。

  3. 有成员变量:

    这就是将资源或其他状态信息附加到对象的方式。

  4. 有成员函数:

    这就是您对对象进行操作的方式。

  5. class从另一个/继承struct

    class这说明了与另一个/struct类型的 is-a 关系。即 A caris-a vehicle, a bikeis-a vehicle。因此carbike继承自vehicle.

现在,您的 Hero.h 文件包含Hero指示它的构造函数和析构函数的类声明(顺便说一句,您不需要(void). 那是旧的 C 风格。在 C++ 中,一个空参数列表()等价于(void).),但它不需要包含任何成员变量或函数。这是因为您继承自Characters. 除非您在将其用作基类之前没有声明。 Characters所以在你的 Hero.h 文件中,你必须在类的声明#include "Character.h"之前声明。这适用于每个头文件。

但是,如果您多次包含该文件,您还应该保护标题的内容。为此,在 Hero.h 的内容周围放置类似这样的内容。

#if defined HERO_H
# define HERO_H

... the contents of Hero.h ...

#endif

对每个头文件执行此操作。为每个文件使用唯一的保护名称。即不要将 HERO_H 用于您的 Character.h 文件。 注意我刚刚注意到您正在使用#pragma once. 这等效于使用防护,但不能在所有编译器之间移植。

进入你的 Hero.cpp 文件,有一些地方出错了。

  1. 您需要包含 Hero.h 文件。

    请记住,C++ 是在使用前声明的,并且每个源文件都是单独编译的。因此,您必须在使用之前声明每个源文件使用的所有内容。由于 Hero 类是在 Hero.h 头文件中声明的,因此您必须包含该头文件。

  2. 全局变量:

    我看到你正在使用全局变量。不要这样做,当你有应该做同样事情的成员变量时不要这样做。成员变量是该类的每个实例的一部分。换句话说,每次创建类的实例时,您都会为该成员变量拥有一个唯一的内存存储位置,从而允许您拥有多个具有不同状态且不会相互冲突的实例。IE:

    Hero::Hero(int newHp, int newLevel, int newAttack, int newDef)
    {
        cout << "Hero created using Overloaded function!\n";
        Hp = newHp;
        cout << "Hp is: "<< Hp << endl;
        level = newLevel;
        cout << "level is: " << level << endl;
        Attack = newAttack;
        cout << "Attack is: " << Attack << endl;
        Defense = newDef;
        cout << "Defense is: " << Defense << endl;
    }
    

    您还有一个用于Hero. 为什么?拥有这个有什么意义?如果有一点,需要为其设置哪些默认值?查看Character该类,我发现您在调用其默认构造函数时也没有初始化该实例的成员变量。我认为您在这里遇到的问题是您不知道如何初始化从另一个继承的对象,这是合理的,因为它不是立即显而易见的。查看我的最后一个代码片段,并将其与这个新代码片段进行比较:

    Hero::Hero(int newHp, int newLevel, int newAttack, int newDef)
      : Character(newHp, newLevel, newAttack, newDef) // <== initialiser list
    {
        cout << "Hero created using Overloaded function!\n";
        cout << "Hp is: "<< Hp << endl;
        cout << "level is: " << level << endl;
        cout << "Attack is: " << Attack << endl;
        cout << "Defense is: " << Defense << endl;
    }
    

    通过使用初始化列表,我通过调用它的带参数的构造函数来初始化基础对象。这样做就不需要有一个必须有默认构造函数的基类,或者您可以使用默认构造函数来生成您在调用其构造函数时要查找的随机值int,从而无需那个构造函数。有关如何使用该rand()功能的说明,请参见此处

    初始化列表就是这样,用于初始化对象的列表。因此它可以包含多个东西(因此它被称为列表)。它可以包含的其他内容是成员变量的初始值。

    Characters::Characters(int newHp, int newLevel, int newAttack, int newDef)
      : Hp(newHp), level(newLevel)  //... etc
    {
    }
    

    这些需要按照基类初始化程序的顺序(如 Hero 示例中),然后是成员变量,按照它们在类声明中出现的顺序。一些编译器将允许它以任何顺序排列,但同样,这不是可移植的,并且可能导致意外行为。

哦,我注意到的另一件事是您的 Monster.h 文件包含 Hero.h。为什么?Monster.h 文件是否使用 Hero 的实例?不,所以摆脱它。

于 2013-06-14T05:41:53.243 回答