Can't properly transfer data from a class in C++ - c++

I am trying to make a simple game
What will happen is a player will be hit by various objects that result in increase/ decrease of health
The mainGame(); is created just to see if its working properly.
On compilation i get this
(.text$_ZN5gamer7setDataEv[__ZN5gamer7setDataEv]+0x117)||undefined reference to `gamer::mainGame()'|
I tried the friend keyword but that gave me the error of undefined reference to object
class gamer
{
public:
string gName;
int gHealth;
int continueGame;
void mainGame();
void setData()
{
cout << "Enter your name " <<endl;
cin >> gName;
srand(time(0));
gHealth = 100 + (rand()%200);
cout << gName << " has health of " << gHealth << endl;
cout << "Would you like to continue ? 0 for yes" << endl;
cin >> continueGame;
if (continueGame == 0)
{
mainGame();
}
}
};
void mainGame()
{
gamer gamer;
while(gamer.gHealth >= 0 || gamer.gHealth <= 500)
{
cout << " aaaaaa" << endl;
gamer.gHealth -= 50;
cout << gamer.gHealth << endl ;
}
}

You have declared the mainGame function as a member of your gamer class but never actually defined it. You came close, but forgot to declare, in the definition, that it a member of the class. The below should work:
void gamer::mainGame() // This is a member function of `gamer`, so declare it as such!
{
// gamer gamer; // We don't need this reference, as the member function will have...
while(gHealth >= 0 || gHealth <= 500) // ... an implied "this" object when called
{
cout << " aaaaaa" << endl;
gHealth -= 50; // Just using the member name on its own is enough to get it.
cout << gHealth << endl ;
}
}
Inside a member function, you don't need code declaring an object of that class! When the function is called (by an object of the class) the function effectively receives a pointer to the object that called it; you can explicitly access this pointer with the this keyword but, generally, you don't need to. Just using the name of a member variable in that function will reference that member variable for the object that called the function.

Related

Using a map that has a abstract base class pointer and calling a derived class function

I've searched on the web and can't find any solutions to my problem I hope you can help.
So I have constructed an abstract base class and have two derived classes that represents different experiments. (one is actually a derived derived class of my base class) And I made a map as such in a separate header file to store different types of experiments.
//Map class template to store name of experiment and the experiment within a project
typedef map <string, baseData <double>*> ExpContainer;
void search(string searchName, ExpContainer exps) {
ExpContainer::iterator Iter;
Iter = exps.find(searchName); //finds the entry corresponding to searchName and returns the iterator
if (Iter != exps.end()) { //need this as if entry is not found, the return will be end iter.
cout << "Found the experiment " << Iter->first << "." << endl;
Iter->second->print();
}
else {
cout << "Sorry, experiment " << searchName << " is not found" << endl;
}
}
The print() function is different for each experiment type and I know there's a problem called slicing so I've made sure that print() is virtual in the base class. Here's my base class:
namespace mynmsp {
//base class of data can be measurements or errors
template < class T> class baseData {
public:
virtual void print() =0;
virtual ~baseData() {
cout << "Destructor called for the base class." << endl;
}
};
}
Then in my main.cpp I've constructed different types of experiment and I want to print them. Each experiment class has different implementation of the print function that overrides the print function from the base class, like:
void print(){ //do something };
And in my main.cpp I have the map defined as:
ExpContainer project;
And after I have constructed each experiment, I've asked the user for the name of the experiment (expName) and inserted into project as such:
project[expName] = &expC;
I think the insertion is fine as I tested the size of project and it was correct.
However, a runtime error occured when my search function was called like this:
search(name, project);
I don't know if there's a problem with slicing or with my pointers?
I tried to make print() a virtual function in each derived class but that doesn't seem to work either.
Apologies for the long question, please help!
Edit: I've constructed my experiments inside a do while loop while project is declared outside. The whole code is very long but its basics is something like this:
string repeatstr; //user input whether to repeat do while loop or not
bool repeat = true; //condition for staying inside do while loop
ExpContainer project; //declared project to store experiments
do {
string expName;
string ans1; //character to store user input
cout << "What is the name of your experiment? " << endl;
cin >> expName;
cout << "Is this a experiment C ? (y/n)" << endl;
cin >> ans1;
if(ans1 =="y"){
//call the constructor for expC
project[expName] = &expC;
}else {
//call the constructor for expB
project[expName] = &expB;
}
cout << "Do you want to enter another experiment? (y/n)" << endl;
cin >> repeatstr;
if (repeatstr == "n") { repeat = false; }
}while (repeat); //loop over this do-while loop while repeat is true
cout << "There are " << project.size() << " in this database." << endl;
//to retrieve info from a certain experiment
string input, name;
cout << "Would you like to retrieve any experiments (y/n)? " << endl;
input = EitherInput("y", "n");
if (input == "y") {
cout << "Please enter the name of the experiment you want to retrieve: " << endl;
cin >> name;
search(name, project); //code breaks down here!
}
You are saving a pointer to the object that was already destroyed. You can check the addresses that you have in the map, most probably they are the same. You should store your experiment object in dynamic memory
if(ans1 =="y")
{
project[expName] = new expC();
} // Scope ends here and all variable created in it will be destroyed.
else
{
project[expName] = new expB();
} // Scope ends here and all variable created in it will be destroyed.
And after you are done with them you need to call delete on each pointer to avoid memory leak. Also you need to check if the items in the map are already existing, otherwise you will loose pointers to allocated memory which is automatically a memory leak.
I would recommend you to use std::share_ptr< baseData<double> > instead of bare baseData<double>*. Here you can read more about it. And also consider using typedef in order to have more clear syntax.
P.S.
The function
void search(string searchName, ExpContainer exps)
will copy whole map to its body. Use constant reference instead
void search(string searchName, const ExpContainer& exps)
But then you'll also need to declare function print as const:
virtual void print() const = 0;
and override it with const modifier:
virtual void print() const override;
And use constant iterator ExpContainer::const_iterator Iter

How to instantiate a variable from a class with a variable from another class with C++

I'm trying to instantiate a variable Tt1 from a class called ÌnletConditions with the variable Tt0 from another class with the object ein_in.
double InletConditions::Tt1 = ein_in.Tt0;
The variable Tt1 is declared as public static double in the headerfile of the class InletConditions.
class InletConditions {
public:
static double Tt1;
}
The variable Tt0 is declared and instantiated like this:
\\ file Eingabe_Konstanten.h
class Eingabe_Konstanten {
public:
static double Tt0;
}
\\ file Eingabe_Konstanten.cpp
double Eingabe_Konstanten::Tt0 = io_ein.read(1);
io_ein.read(int) refers to a method, which reads in a value from the specified line number (int) from a file. The value should become 293.15.
How can I achieve that the value of Tt1 also becomes 293.15? In the output it is just 0.
int main() {
Eingabe_Konstanten ein;
InletConditions in;
std::cout << ein.Tt0 << endl;
std::cout << in.Tt1 << endl;
}
Output:
293.15
0
I would be pleased if anyone could help me, since I am new to programming and don't know what topic this problem is related to.
Thanks in advance.
Static variables refer to the class itself and not to a particular object of that class. As such you must call them using the scope resolution operator of the class:
InletConditions::Tt1 = Eingabe::Tt0;
std::cout << Eingabe::Tt0 << endl;
std::cout << InletConditions::Tt1 << endl;
LIVE DEMO
Why not just use:
int main() {
Eingabe_Konstanten ein;
InletConditions in;
in.Tt1 = ein.Tt0; //You need to assign the value of ein.Tt0 to in.Tt1 here
std::cout << ein.Tt0 << endl;
std::cout << in.Tt1 << endl;
}

How to access info from an instance from another instance in c++?

I am just started learning OOP concepts and to help myself learning, I have created a Characters class. From this class I have made instance called main and an instance called monster. Here is the code for the class:
#include <iostream>
#include <string>
using namespace std;
class Character {
public:
string name;
float health;
int attackLevel;
int defenseLevel;
void setAttr(string sName,float sHealth, int sAttackLevel, int sDefenseLevel) {
name = sName;
health = sHealth;
attackLevel = sAttackLevel;
defenseLevel = sDefenseLevel;
}
void attack(int whatInstanceToAttack) {
whatInstanceToAttack.hitpoints -= 20; //obviously not valid but how do i do this?
return whatInstanceToAttack;
}
int defend(string defend) {
int damageRelieved = defenseLevel * 2;
return damageRelieved;
}
};
int main() {
Character main;
Character monster;
main.setAttr("Rafael",200,100,30);
monster.setAttr("Monster1",30,40,30);
cout << "Default Values for Raf are;" << endl;
cout << main.name << endl;
cout << main.health<< endl;
cout << main.attackLevel << endl;
cout << main.defenseLevel << endl;
cout << "Default values for monster are" << endl;
cout <<monster.name << endl;
cout <<monster.health << endl;
cout << monster.attackLevel<< endl;
cout << monster.defenseLevel << endl;
return 0;
}
Basically what I want to do is somehow access the monster instance via the main instance. I want to do this by running the attack method. So if I run
main.attack(monster);
then I want the monster to lose 20 hitpoints.
How do I go about doing this?
All you need is to pass reference of Character in attack method.
I think you must be aware of pass by value and pass by reference concept. If not you can read it here
void attack(Character &whatInstanceToAttack) {
whatInstanceToAttack.hitpoints -= 20; //obviously not valid but how do i do this?
}
Yes you can access the variables of an instance from another instance of the same class. You need to use a reference to the object to ensure the changes are reflected in the other instance. So here is what your attack function should look like.
void attack(Character &c)
{
c.hitpoints - = 20;
}
Now when you call main.attack(monster) from the main() function, the hitpoints of monster will get decremented by 20.
As a side note, it is considered a good practice to make the data members of a class private, to avoid illegal access/modification of the data. Always use the member functions as an interface to your class instances.
overload the method attack and you can pass by value or reference as per your requirement.
void attack(Character chr)
or
void attack(Character &chr)

C++ Can't figure out output for a class that holds player information. It outputs garbage

I've been pulling my hair out trying to figure out this program. The class has to hold 3 player's info and output their info. My output function is not outputting from my set/get functions. Also, if I output the array indexes the program crashes (that's the array indexes are commented out in the Output function).
edit: I'll just show one profile to keep the code smaller
Any help is appreciated.
#include <cstdlib>
#include <iostream>
using namespace std;
class PlayerProfile
{
public:
void output();
void setName1(string newName1); //player's name
void setPass1(string newPass1); //player's password
void setExp1(int newExp1); //player's experience
void setInv1(string newInv1[]); //player's inventory
void setPos1(int newX1, int newY1); //player's position
string getName1();
string getPass1();
int getExp1();
string getInv1();
int getPos1();
private:
string name1;
string pass1;
int exp1;
string inv1[];
int x1;
int y1;
};
int main(int argc, char *argv[])
{
PlayerProfile player;
cout << "This program generates three player objects and displays them." << endl;
cout << endl;
player.output();
system("PAUSE");
return EXIT_SUCCESS;
}
void PlayerProfile::setName1(string newName1)
{
newName1 = "Nematocyst";
name1 = newName1;
}
void PlayerProfile::setPass1(string newPass1)
{
newPass1 = "obfuscator";
pass1 = newPass1;
}
void PlayerProfile::setExp1(int newExp1)
{
newExp1 = 1098;
exp1 = newExp1;
}
void PlayerProfile::setInv1(string newInv1[])
{
newInv1[0] = "sword";
newInv1[1] = "shield";
newInv1[2] = "food";
newInv1[3] = "potion";
inv1[0] = newInv1[0];
inv1[1] = newInv1[1];
inv1[2] = newInv1[2];
inv1[3] = newInv1[3];
}
void PlayerProfile::setPos1(int newX1, int newY1)
{
newX1 = 55689;
x1 = newX1;
newY1 = 76453;
y1 = newY1;
}
string PlayerProfile::getName1()
{
return name1;
}
string PlayerProfile::getPass1()
{
return pass1;
}
int PlayerProfile::getExp1()
{
return exp1;
}
string PlayerProfile::getInv1()
{
return inv1[0], inv1[1], inv1[2], inv1[3];
}
int PlayerProfile::getPos1()
{
return x1, y1;
}
void PlayerProfile::output()
{
cout << "Player Info - " << endl;
cout << "Name: " << name1 << endl;
cout << "Password: " << pass1 << endl;
cout << "Experience: " << exp1 << endl;
cout << "Position: " << x1 << ", " << y1 << endl;
cout << "Inventory: " << endl;
/*cout << inv1[0] << endl;
cout << inv1[1] << endl;
cout << inv1[2] << endl;
cout << inv1[3] << endl; */
}
This is the output that I am getting:
This program generates three player objects and displays them.
Player Info -
Name:
Password:
Experience: -2
Position: 3353072, 1970319841
Inventory:
Press any key to continue . . .
I'm sorry if I sound like an idiot, this is the first time I have programmed with classes and I am very confused.
First:
You do not have a constructor declared or defined in your class so when you compile, the compiler provides you with a default constructor.
The line
PlayerProfile player;
calls the default constructor provided by the compiler. This default constructor only allocates memory for your class member variables, but does not set their values. This is why name1, pass1, exp1, x1, y1 are not outputting what you expect.
Second:
C++ will not call get or set functions for you, and I think you are misunderstanding how c++ functions work.
this
void PlayerProfile::setName1(string newName1)
{
name1 = newName1;
}
is a function definition. You do not need to assign newName1 inside the function. It's value is passed to the function when a line like
setName1("Nematocyst");
is executed.
If you write a constructor, you can use it to call your set functions, and pass them the values you want to set member variables to.
If you do not want to write a constructor, you can call class functions/methods from main with:
player.setName1("Nematocyst");
Third:
Your program crashes because you are not using arrays properly. Here is a tutorial on how to declare an array and access it's contents.
Generally, I think you are trying to run before you know how to walk. Try not to get frustrated. Learn how arrays work, how functions work, and then how classes work. I hope this is not your homework assignment!

How to access array from a class in c++? (closed)

I'm writing a copy constructor for my class, Vehicle, but I'm having trouble accessing an array that the class has in this constructor. I set other values using dot notation (vehi.vin) and that works fine, as expected. So I tried to access the array using the same idea vehi.accessories[0] but that seems to return a null value rather than the string that's actually there. And I know when I first initialize the class that this array does have the proper values in it because I can print them out. So my question is, how can I access an array from a class? Am I using dot notation wrong? Can I not use dot notation for arrays? Do I just need a get method?
code -
vehicle.cpp
Vehicle::Vehicle(const Vehicle& vehi)
{
//get values and set them equal to the local object's attributes
vin = vehi.vin;
for(int i = 0; i < vehi.numAccessories; i++)
{
//cout << "get here\n";
accessories[i] = vehi.accessories[i];
cout << accessories[i] << " " << vehi.accessories[i] << endl;
}
}
how accessories gets its values:
for(int i = 0; i < numAccessories; i++) //loop through file until all accessories for the car have been put into the array
{
getline(fin, accessories[i]); //put accessory in the next spot in the accessory array
cout << "Accessory " << (i+1) << ": " << accessories[i] << endl;
}
main.cpp declaration of Vehicle object. The constructor reads the values in using the file object passed to it.
Vehicle temp(fin);
vehicle.h
private:
string accessories[50]; //array of accessories stored in string form
Edit: When I try calling the copy constructor directly it works fine but when calling the printVehicle() function it seems to get there but fail somehow. The code below does what I want and shows me that the copy constructor works fine, so I guess it's the way it's invoked from printVehicle()
main.cpp:
Vehicle test(fin);
test.startAcc();
cout << endl << test.nextAcc() << endl;
Vehicle test2(test);
test2.startAcc();
cout << endl << test2.nextAcc() << endl;