如何在另一个包含对象的文件中创建一个函数并从 main 调用它

How to create a function in another file with objects and call it from main

本文关键字:函数 一个 调用 main 包含 另一个 对象 创建 文件      更新时间:2023-10-16

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

//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 constructorn";
}
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;
}

首先,不要将变量声明为全局变量,而是将它们声明为成员变量!声明全局变量时,程序中将只有一个该变量的实例,因此,如果创建(例如(两个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());

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

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

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

  1. 具有构造函数:

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

  2. 有一个析构函数:

    这将解除分配对象使用的资源。

  3. 具有成员变量:

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

  4. 具有成员功能:

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

  5. 继承自另一个class/struct

    这表示与另一种class/struct类型的 is-a 关系。 即carvehiclebikevehicle。 因此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. 全局变量:

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

    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 的实例? 不。 所以摆脱它。

相关文章: