I have been trying to access a series of integers from the main class, and then display them inside a method.
However, I've been having a bit of trouble with this due to my own ineptitude with a language I've not been coding in for too long.
After quite a bit of searching, I have been unable to find anything that can help me. How would I go about doing this, if it's possible at all?
#include "inventory.h"
inventory::inventory(){
int maxhealth = 100;
int maxmana = 0;
int health = 100;
int mana = 0;
int level = 1;
int agility = 1;
int strength = 1;
int healthpotions = 0;
int manapotions = 0;
int armourlevel = 0;
int weaponlevel = 0;
int crystals = 0;
int gold = 0;
int rock = 0;
int wood = 0;
}
string inventory::getinv(){
return inventory; //I know this sort of return thing won't work, just a placeholder until I figure out what to do.
}
This is what I have been using thus far, but I'm having a hard time even getting that to not display the "Member 'X' was not initialized in this constructor." I'm clearly doing something quite wrong.
Inventory.h:
#ifndef INVENTORY_H_
#define INVENTORY_H_
#include <iostream>
class inventory{
private:
int maxhealth;
int maxmana;
int health;
int mana;
int level;
int agility;
int strength;
int healthpotions;
int manapotions;
int armourlevel;
int weaponlevel;
int crystals;
int gold;
int rock;
int wood;
public:
inventory();
string getinv();
};
#endif /* INVENTORY_H_ */
EDIT: Thanks to the help so far I've been able to get rid of most of the errors. The only one left is "..\src\zoria.cpp:1616:36: error: 'rock' was not declared in this scope"
You do not need the type in the constructor to access the member variables, otherwise the compiler would think that you are trying to declare new local variables.
Here is a basic correction for the inventory.cpp file:
#include "inventory.h"
inventory::inventory(){ // this is the constructor
maxhealth = 100;
maxmana = 0;
health = 100;
mana = 0;
level = 1;
agility = 1;
strength = 1;
healthpotions = 0;
manapotions = 0;
armourlevel = 0;
weaponlevel = 0;
crystals = 0;
gold = 0;
rock = 0;
wood = 0;
}
string inventory::getinv(){
return "inventory"; //I know this sort of return thing won't work, just a placeholder until I figure out what to do.
}
Note the "" added to the placeholder (return "inventory") to make it a valid string.
Note: You cannot access the variable that is in a class directly without an object of the class, even if it is declared public (static being the only exception). However you have declared all your member variables as private and will thus require getter and setter functions to access their values.
EDIT:
Classes are like containers which contain things. But just the definition of a class is just like a stencil which can be used to create objects of that type. The actual existence of the object occurs when you write inventory someobject;.
Now every class has a special function called the constructor which goes by the name of the class itself and is called as soon as the an object of this class is declared. You can initialize all member variables of the class in the constructor.
To access the members of a class you have to use the . dot operator. Members have to be declared public if they need to be directly accessed outside the class' body.
So you change the class definitions like this:
inventory.h:
#ifndef INVENTORY_H_
#define INVENTORY_H_
class inventory{
public:
int maxhealth;
int maxmana;
int health;
int mana;
int level;
int agility;
int strength;
int healthpotions;
int manapotions;
int armourlevel;
int weaponlevel;
int crystals;
int gold;
int rock;
int wood;
inventory();
void printinv();
};
#endif /* INVENTORY_H_ */
and
inventory.cpp:
#include "inventory.h"
#include <iostream>
using namespace std;
inventory::inventory()
{
maxhealth = 100;
maxmana = 0;
health = 100;
mana = 0;
level = 1;
agility = 1;
strength = 1;
healthpotions = 0;
manapotions = 0;
armourlevel = 0;
weaponlevel = 0;
crystals = 0;
gold = 0;
rock = 0;
wood = 0;
}
void inventory::printinv(){
cout << "LEVEL: " << level << endl;
cout << "HEALTH: " << health << endl;
cout << "MANA: " << mana << endl;
cout << "AGILITY: " << agility << endl;
cout << "STRENGTH: " << strength << endl;
cout << endl;
cout << "HEALTH POTIONS: " << healthpotions << endl;
cout << "MANA POTIONS: " << manapotions << endl;
cout << endl;
cout << "ARMOUR LEVEL: " << armourlevel << endl;
cout << "WEAPON LEVEL: " << weaponlevel << endl;
cout << "CRYSTALS: " << crystals << endl;
cout << endl;
cout << "GOLD: " << gold << endl;
cout << "ROCK: " << rock << endl;
cout << "WOOD: " << wood << endl;
}
Now declare the object of the class in main like:
inventory inv;
and access every member variable (such as maxhealth, maxmana, health, mana, level, agility, strength, healthpotions, manapotions, armourlevel, weaponlevel, crystals, gold, rock and wood) like:
inv.gold = 10;
inv.rock++;
etc. throughout the code.
and to display the inventory replace all the redundant display code with:
inv.printinv();
everywhere.
See zoria.cpp here, I have done the changes for all display code and changed the variable accesses for: maxhealth, maxmana, health and healthpotions you also have to do it for the rest of the variables like: mana, level, agility, strength, manapotions, armourlevel, weaponlevel, crystals, gold, rock and wood.
Hope this helps. Tell if there are any more questions.
In Inventory.h you define the member variables (maxhealth, maxmana etc) and in Inventory.cpp, you should declare them in its constructor. The problem is that you're redeclaring them. Try removing the "int" from every variable in the constructor because you only need to specify the type when you define the variable.
A few points here:
In you constructor you are shadowing the instance variables by method-local re-definition of identically named variables. Please, look up on how to initialize instance member variables in constructors.
You try to implicitly convert an instance of your inventory class into a std::string with the signature of your getinv() method, but you have not defined any operator for this kind of conversion.
(probably related to (2)) From the error you posted, I assume you are using getinv() something along the line of
inventory my_inventory{};
int inv = my_inventory.getinv();
This will not work as there is no implicit conversion from std::string to int defined. Change the return type of inventory::getinv() to int and return an actual int there.
Related
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)
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!
I'm trying to figure out how I can or why I can't access the member of this class. First I'll show you what works so you know what I'm thinking, then I'll show you what I can't seem to do.
What I can do is this: I have a class with a member. I make an pointer array of that class and make NEW pieces of it (through loop) and that's fine and all. I can also make another class with a similar array and even make NEW instances of that as well and initialize them, but when I try to access them, I have problems.
This code almost works fine:
#include <iostream>
using namespace std;
class testClass{
public:
int number;
};
class testPoint{
public:
testClass testInstance;
testClass *testclassArray[5];
void makeArray();
void setToI();
};
void testPoint::makeArray(){
for (int i = 0; i < 5; i++){
testclassArray[i] = new testClass;
}
}
void testPoint::setToI(){
for (int i = 0; i < 5; i++){
(*testclassArray[i]).number = i;
}
}
int main(void){
testPoint firstTestPoint;
firstTestPoint.makeArray();
firstTestPoint.setToI();
// EXCEPT FOR THIS LINE this is where I have problems
cout << firstTestPoint.(*testclassArray[0]).number << endl;
return 0;
}
I know this should work becuase this works
int main(void){
testPoint firstInstance;
firstInstance.testInstance.number = 3;
cout << firstInstance.testInstance.number << endl;
// and this works
return 0;
}
and this works
int main(void){
testClass *testPointer[5];
for (int i = 0; i < 5; i++){
testPointer[i] = new testClass;
(*testPointer[i]).number = i;
}
cout << (*testPointer[0]).number << endl;
return 0;
}
so why can't I access the members on the cout function the same way?
The following is invalid syntax:
cout << firstTestPoint.(*testclassArray[0]).number << endl;
The most common way to write what you are trying to accomplish is:
cout << firstTestPoint.testclassArray[0]->number << endl;
But, if you prefer, you can also write:
cout << (*firstTestPoint.testclassArray[0]).number << endl;
(The second way is far less common.)
The . operator is used to access members of direct objects, e.g. a.member where a might be declared as struct A a;. The -> operator is used to access members of indirect objects (aka pointers to objects), e.g. b->member where b might be declared as struct B* b = new B();.
You are dereferencing the variable in an incorrect way.
Try doing
cout << firstTestPoint.testclassArray[0]->number << endl;
instead.
In the same way the second attempt, where it works for you, could also have been written:
out << testPointer[0]->number << endl;
Try using this code:
cout << firstTestPoint.testclassArray[0]->number << endl;
So I'm working on a program which is a game of Blackjack. I have a class called Player for each player in the game. The problem lies in this block of code here which is inside Player.cpp:
void Player::SetFunds(int amt){
cout << "setting funds:" << endl;
cout << m_funds << "m_funds" << endl;
m_funds = amt;
cout << "done" << endl;
}
When compiled, I get a segmentation fault. The line "setting funds:" prints, but I cannot print m_funds, nor can I set it to amt (I tried it before adding the print statement for m_funds).
Here's the declaration of the function in Player.h (which is included in Player.cpp).
void SetFunds(int amt);
And here is where I have m_funds, among other private variables in the Player class.
private:
char* m_name;
int m_funds;
int m_bet;
Hand m_hand;
bool m_busted;
};
Is there something I'm missing? Why can't I seem to access a private Player class variable even though I am inside a Player class function? Is it possible the error is elsewhere even though I get a segmentation fault right after the "setting funds" prints?
Also, I can change the private variables in the constructor just fine, as follows:
Player::Player(char *name, int amt){
m_name = name;
cout << amt << endl; //Amount prints as 100
m_funds = amt; // sets m_funds to 100
cout << m_funds << endl; //m_funds prints as 100 just fine
m_bet = 0;
m_hand = Hand();
m_busted = false;
}
EDIT:
Here is where I call the function SetFunds inside Blackjack.cpp:
(m_players is a vector of Players as a private variable of Blackjack class.) Again, amt couts to 100.
void Blackjack::SetPlayerFunds(int player, int amt){
cout << amt << endl;
m_players[player].SetFunds(amt);
}
And here is where I call that function from Project.cpp (which contains main):
(Note: This is for a project where I cannot edit this file and have to base my code around it)
Blackjack *CreateGame(int argc, char *argv[]) {
char **names;
int *funds;
int numPlayers;
Blackjack *game;
numPlayers = ProcessArgs(argc - 1, &argv[1], names, funds);
game = new Blackjack(names, numPlayers);
for (int p = 0; p < numPlayers; p++) {
game->SetPlayerFunds(p, funds[p]);
}
EDIT 2:
Here is the Blackjack class constructor which is called inside Blackjack::CreateGame.
Blackjack::Blackjack(char *names[], int numPlayers){
std::vector<Player> m_players;
m_dealer = Player();
int amt = 100;
for(int i = 0; i < numPlayers; i++){
Player player(names[i], amt);
m_players.push_back(player);
}
}
Your issue is in the Blackjack constructor.
Blackjack::Blackjack(char *names[], int numPlayers){
std::vector<Player> m_players;
m_dealer = Player();
int amt = 100;
for(int i = 0; i < numPlayers; i++){
Player player(names[i], amt);
m_players.push_back(player);
}
}
You are creating m_player on the heap in the constructor, assigning and adding players, but probably never initializing the real member of the same name in the class...
To solve the issue, remove the std::vector m_players;
Umm, It seems that this pointer is strange..
I suggest this test code.
void Blackjack::SetPlayerFunds(int player, int amt)
{
cout << amt << endl;
// if "m_players" is std::vector
m_players.at(player).SetFunds(amt);
// elif "m_players" is C-array
if (player >= sizeof(m_players)/sizeof(m_players[0]))
abort(); // assert(false) or setting breakpoint will be better, if you can use debugger
m_players[player].SetFunds(amt);
}
There are a lot of questions about static vs global here but I think my question is a bit different.
I want to know if there is a way to share a variable placed in a namespace across files the way static variables in a class can.
For example, I coded this:
//Foo.h
class Foo
{
public:
static int code;
static int times_two(int in_);
};
namespace bar
{
static int kode;
}
-
//Foo.cpp
int Foo::code = 0;
int Foo::times_two(int in_)
{
bar::kode++;
code++;
return 2*in_;
}
-
//main.cpp
int main()
{
cout << "Foo::code = " << Foo::code << endl;
for(int i=2; i < 6; i++)
{
cout << "2 x " << i << " = " << Foo::times_two(i) << endl;
cout << "Foo::code = " << Foo::code << endl;
cout << "bar::kode = " << bar::kode << endl;
if(i == 3)
{
bar::kode++;
}
}
}
All that yielded this for code and kode:
Foo::code = 1,2,3,4
bar::kode = 0,0,1,1
Once again, is there a way to share a variable placed in a namespace across files the way static variables in a class can? The reason I ask is because I thought I would be able to shield myself from confliciting global variables by using :: notation, and just found out I could not. And like any self-disrespecting programmer, I believe I am doing it wrong.
Yes:
//bar.h
namespace bar
{
extern int kode;
}
Outside of a class or struct, static has a whole different meaning. It gives a symbol internal linkage. So if you declare the same variable as static, you will actually get a different copy for all translation units, not a unique global.
Note that you'll need to initialize the variable once:
//bar.cpp
namespace bar
{
int kode = 1337;
}