如何在另一个包含对象的文件中创建一个函数并从 main 调用它
How to create a function in another file with objects and call it from main
我希望能够制作战斗场景并将其放入函数中,但是每次尝试时,我都必须在不同的头文件中创建对象,然后我无法在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
定义的实例。 一个类有几个关键组件,但并非所有组件都存在:
-
具有构造函数:
这将设置
class
的任何新实例的初始状态,并通常分配对象使用的资源。 -
有一个析构函数:
这将解除分配对象使用的资源。
-
具有成员变量:
这就是资源或其他状态信息附加到对象的方式。
-
具有成员功能:
这就是您对对象进行操作的方式。
-
继承自另一个
class
/struct
:这表示与另一种
class
/struct
类型的 is-a 关系。 即car
是vehicle
,bike
是vehicle
。 因此car
和bike
继承自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 文件,有一些问题。
您需要包含 Hero.h 文件。
请记住,C++在使用前声明,每个源文件都是单独编译的。因此,在使用之前,必须声明每个源文件使用的所有内容。 由于 Hero 类是在 Hero.h 头文件中声明的,因此必须包含该头文件。
全局变量:
我看到您正在使用全局变量。 不要这样做,当你有应该做同样事情的成员变量时,不要这样做。 成员变量是该类的每个实例的一部分。 换句话说,每次创建类的实例时,该成员变量都有一个唯一的内存存储位置,允许您拥有多个实例,这些实例将具有彼此不冲突的不同状态。 即:
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 的实例? 不。 所以摆脱它。
- 函数向量_指针有不同的原型,我可以构建一个吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何仅为一个函数添加延迟
- 构造函数正在调用一个使用当前类类型的函数
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 如何创建函数管道,以便函数一个接一个地运行?
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 在c++中的复制构造函数/一个声明语句中的初始化的延续中使用chain方法
- C :基类调用自己的虚拟函数 - 一个反图案
- 如何在这个交换函数(一个单独的链表)中找到错误
- 两个相同的函数(一个使用模板模式,另一个不使用)
- 你怎么能一次给一个函数一个参数呢
- 为什么要做两个函数?(一个是非const,另一个是const)
- 当代码在其他地方使用时,如何保证函数一个接一个地被调用