Class value accessible from multiple files and functions c++ - c++

I apologize before-hand if this question has been asked before.
I put all my skills with google to use and still nothing so if this question has been answered before please just link the answer and I'll essentially end the question.
Anyway, with all that out of the way, my problem is that I have a class "Player.hpp" and a corresponding "Player.cpp" in which I have defined the location system for the "player" I can initialize the value fine (which is one of the functions of the class) but then when the player goes to the "play()" function (which holds the bones of the game and is located in another .cpp file) when I use the function to get the Location I stored there is nothing stored... any help would be appreciated.
If you don't understand what I'm asking please comment and I'll elaborate.
Code Below:
//Player.hpp
class player
{
public:
std::string getLocation();
void setLocation(std::string local);
void initLocation();
private:
std::string location;
};
//Player.cpp
void player::initLocation()
{
player::location = "B0";
return;
}
std::string player::getLocation()
{
return player::location;
}
void player::setLocation(std::string local)
{
player::location = local;
return;
}
//Main.cpp
//....
player plays;
plays.initLocation();
//....
//Game.cpp
//...
player plays;
std::string local = plays.getLocation(); //When I check there isn't a value that gets stored...
if(local.find(...)...)
Again, any help is appreciated and I apologize if a question like this has already been asked.
Edit:
I guess I should have clarified that I also want to change the value stored as the player progresses from room to room (as this is a zork style game I'm making)

Assuming that each instance of player could be in a separate location, you can resolve this issue by initializing the player's location with the default location in its constructor. This removes the need for initLocation(), and thus there is no need to call it from Main.cpp.
//Player.hpp
class player
{
public:
std::string getLocation();
void setLocation(std::string local);
player () : location("B0") {}
private:
std::string location;
};

It looks as if you omitted static in front of the class variable declaration:
class player
{
// ...
static std::string location;
};
... which then also requires a definition. Of course, the definition becomes a prime location to also initialize the value:
// Player.cpp
std:string player::location("B0");
making the initialization function unnecessary.

Related

(C++) Pointers to Pointers of objects in different classes

everyone. I'm working on a final project for school and it's coming along great, but I've run into a bit of a problem with trying to use a pointer to a pointer. I'll do my best to explain the problem below:
So I have a class called Player that sort of looks like this:
class Player
{
Player();
int health;
void adjustHealth(int);
};
Player::Player()
{
health = 40;
}
void Player::adjustHealth(int adjust)
{
health += adjust;
}
I have another class called Shelter, that include "Player.h" and looks a little like this:
class Shelter
{
Shelter();
Player* player; // Create a pointer to Player class.
};
In the Shelter header file, I have the following in my default constructor:
Shelter::Shelter()
{
...Other code here.
player = new Player();
}
In the Shelter header file, I use this new player for things like:
player->adjustHealth(-1); // Subtract one health from the player.
Which works great.
The problem I'm facing is with creating another class called Church, that is in a separate header file and acts as a separate location in the game. I want Church to use the same player that Shelter does, so it has all of the same stats, etc, rather than creating a new player in Church (which is what I did in Shelter.h).
Right now, I have something like:
class Church
{
Church();
Shelter **cplayer; // This is supposed to be the pointer to the pointer.
};
The default constructor is where I'm having my problem. I want to use the same player from Shelter, not create a new player like I did in Shelter.
Church::Church
{
What should I do here?
}
I've tried a number of things, but I can't quite get it working. Eventually I want to be able to do something like this:
player->adjustHealth(-1); // Subtract one health from the player.
Only in Church, so that player's stats, like health, are adjusted no matter which location they are in.
I hope my question makes sense. If not, I can try to clarify better. Anyway, thanks in advance.
The problem I'm facing is with creating another class called Church, that is in a separate header file and acts as a separate location in the game. I want Church to use the same player that Shelter does, so it has all of the same stats, etc, rather than creating a new player in Church
This sounds like an ideal situation to use std::shared_ptr.
class Shelter
{
Shelter();
std::shared_ptr<Player> player; // Create a pointer to Player class.
// Provide a public accessor
public:
std::shared_Ptr<Player> getPlayer() const { return player; }
};
and
class Church
{
Church(std::shared_ptr<Player> pl) : player(pl) {}
std::shared_ptr<Player> player;
// You haven't explained in your post why you need this.
// Maybe you don't need it.
// Shelter** shelter;
};

Using an object outside of its declaration file (C++)

(it is be possible that this question has been asked very often already and i am sorry about this repost, but anything i found just didnt help me, since i am relatively a beginner at c++)
so here is an example to show my problem
i have the class monster
class Monster{
public:
Monster();
void attack();
private:
int _health;
int _damage;
};
and i have the class Level
class Level{
Level();
};
i have created the object "snake" from the class Monster in my "main.cpp"
#include "Monster.h"
int main(){
Monster snake;
}
now what do i do if i want to use "snake" in my "Level" class? if i want to do "snake.attack();" inside of "Level.cpp" for example?
If i declare it again in "Level.cpp" it will be a seperate object with its own attributes wont it?
i have always been making the member functions of my classes static until now, so i could do "Monster::attack();" anywhere in my program but with this tachnique i cant have multiple objects doing different things depending on their attributes (snake1, snake2, bat1, etc...)
thanks for the help in advance!
(and sorry for the possibly reoccuring question)
Presuming those snips are your .h files.
Your level.cpp should something like this:
#include "level.h" // its own header
#include "monster.h" // header with Monster::attack() declaration
Level::DoAttack(Monster& monster) { // using snake as parameter.
health = health - monster.attack(); // monster hits us, subtract health.
}
monster.h would be
class Monster{
public:
Monster();
void attack();
private:
int _health;
int _damage;
};
and monster.cpp
Monster::attack() {
// code to calculate the attack
}
I could not completely understand your questions.But from what I understood.I think you want to access a Monster object instantiated in main() to be used inside level.So,here is what you can do.Add a constructor inside the level class which takes a monster object as an argument.Then instantiate a level object and pass the monster object in it.Like this,
Level l=new Level(snake);
By declaring a class you're not creating any objects. You normally declare a class by including the corresponding header file.
So, in Level.h you'd #include <Monster.h>, then you can reference it inside Level.
But seriously, you can't write much C++ code without understanding the basic things such as declaration vs. definition, header files (.h), classes vs. objects, pointers and references, etc. It would be best to invest in a book or at least to read some tutorials online.

Initialize class variable by passing a reference to it

I have a quite interesting and funny C++ exercise:
This the imposed main:
int main(void)
{
Exam e = Exam(&Exam::cheat);
e.kobayashiMaru = &Exam::start;
(e.*e.kobayashiMaru)(3);
Exam::cheat = true;
if (e.isCheating())
(e.*e.kobayashiMaru)(4);
return (0);
}
And this is the asked output:
[The exam is starting]
3 Klingon vessels appeared out of nowhere.
You lost again.
[The exam is starting]
4 Klingon vessels appeared out of nowhere.
Win !
You now need to create the Exam class to get the correct output.
Here is what I've done:
class Exam
{
public:
Exam(bool *_cheat);
typedef void (Exam::*func)(int);
void start(int);
bool isCheating();
static bool cheat;
func kobayashiMaru;
};
I encounter problems with the Exam(&Exam::cheat) thing. What I understand so far is that Exam is taking the address of it's own cheat variable. When entering the Exam's constructor cheat is uninitialized. So for me I would initialize it here with false.
Exam::Exam(bool * _cheat)
{
*_cheat = false;
}
But by doing this I get a multiple definition with Exam(&Exam::cheat). I'm not sure about my reflection, can maybe someone enlighten me on what's really happening here?
Change:
static bool cheat;
to:
bool cheat;
inside your Exam class to allow every new object handle its own cheat variable with its own value.
Constructor will initialize your cheat variable by given value while you creating new object with constructor like this:
Exam::Exam(bool isCheating)
{
this->cheat = isCheating;
}
Or if you want to initialize cheat variable as false/true by default you can make constructor like this:
Exam::Exam()
{
cheat = false;
//or cheat = true;
}
You can handle multiple constructors too.
Now to create new object from Exam class use:
Exam *exam1 = new Exam(true); //Will initialize cheat as false
Exam *exam2 = new Exam(false); //Will initialize cheat variable as true
Then access your methods inside exam1 and exam2 object like this:
exam1->methodName(1243);
exam2->secondMethodName(true);
exam2->thirdMethodName();
exam3->addFriend(&exam1);
Those ones are just examples.
Hope I understood your problem. :)
You have a few issues (described in comments below)
class Exam
{
public:
// If cheat is supposed to be a member variable assigned to each instance, passing a pointer to itself is silly and unnecessary
// If cheat is supposed to be shared between all instances of exam, passing a pointer to itself is silly and unnecessary
Exam(bool *_cheat);
static bool cheat;
// these two declarations are unnecessary. They do nothing but add complexity where it is not needed
typedef void (Exam::*func)(int);
func kobayashiMaru;
void start(int);
bool isCheating();
};
I encounter problems with the Exam(&Exam::cheat) thing. What I
understand so far is that Exam is taking the address of it's own cheat
variable. When entering the Exam's constructor cheat is uninitialized.
So for me I would initialize it here with false.
Static variables are initialized before the creating of the first instance of a class. The problem you have is two-fold: 1) you haven't initialized your static member variable, 2) you aren't treating it as a static member variable.
Declaring a variable as static means it will be shared between all instances of the class (e.g. there will be 1 memory location for cheat). Unless you want everyone taking the Exam to cheat as soon as 1 person cheats, this is not likely what you want.
To fix it, you would want your Exam class to look more like this:
class Exam
{
public:
Exam(bool cheat) : m_cheat(cheat) {}
// don't expose member variables directly - use accessor functions
void setCheating(bool cheat) { m_cheat = cheat; }
bool isCheating() const { return m_cheat; }
void start(int);
private:
bool m_cheat;
};
The corresponding changes to your main function
int main(void)
{
Exam e(false);
e.start(3);
e.setCheating(true);
if (e.isCheating())
e.start(4);
return 0;
}

How to initialize a static member object?

I didn't know that I didn't know this :) . and a similar question here didn't help much.
So here i am asking. Please Consider the following class:
//in Agent.h
class Agent : public ns3::Object{
private:
//...
static BaseWifi m_wifi;
//...
};
is this :
//Agent.cpp
BaseWifi temp;
BaseWifi Agent::m_wifi = temp;
very much different from this:
//Agent.cpp
BaseWifi Agent::m_wifi = BaseWifi();
The second approach doesn't work for me.
why and how?
I don't want to trouble you with more codes coz I faced this problem deep in my program. The program generate seg faults as things(members) inside BaseWifi's constructor are not initialized correctly. when those uninitialized internal members are used, seg faults occur.
Thank you in advance for your kind comments and answers.
p.s.:
In fact I found this issue when I hadn't yet initialized this static member and I was deleting an extra line :
BaseWifi temp;
in my main(), which added more to my confusion!!!(this one could be dependent on what I put in BaseWifi's constructor, so dont mind it for now)
Update-1:
For those who would like to see the BaseWifi:
class BaseWifi {
ns3::WifiHelper m_wifiHelper; // a wifi helper apply to setup vehicles Wifi
ns3::NqosWifiMacHelper m_wifiMacHelper; // a wifi mac helper apply to setup vehicles Wifi
ns3::YansWifiPhyHelper m_wifiPhyHelper; // a wifi phy helper apply to setup vehicles Wifi
std::string m_phyMode;
double m_rss; // -dBm
bool m_init_done;
public:
BaseWifi();
virtual void init();
ns3::NetDeviceContainer Install(ns3::NodeContainer &c);
virtual ~BaseWifi();
};
BaseWifi::BaseWifi() {
m_init_done = false;
m_rss = -80;
m_phyMode ="DsssRate1Mbps";
// TODO Auto-generated constructor stub
init();
}
void BaseWifi::init() {
NS_LOG_UNCOND("inside BaseWifi::init()");
m_wifiHelper.SetStandard (ns3::WIFI_PHY_STANDARD_80211b);
m_wifiPhyHelper = ns3::YansWifiPhyHelper::Default ();
// This is one parameter that matters when using FixedRssLossModel
// set it to zero; otherwise, gain will be added
m_wifiPhyHelper.Set ("RxGain", ns3::DoubleValue (0) );
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
m_wifiPhyHelper.SetPcapDataLinkType (ns3::YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
ns3::YansWifiChannelHelper wifiChannel;
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
// The below FixedRssLossModel will cause the rss to be fixed regardless
// of the distance between the two stations, and the transmit power
wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",ns3::DoubleValue (m_rss));
m_wifiPhyHelper.SetChannel (wifiChannel.Create ());
// Add a non-QoS upper mac, and disable rate control
m_wifiMacHelper = ns3::NqosWifiMacHelper::Default ();
m_wifiHelper.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",ns3::StringValue (m_phyMode),
"ControlMode",ns3::StringValue (m_phyMode));
// Set it to adhoc mode
m_wifiMacHelper.SetType ("ns3::AdhocWifiMac");
m_init_done = true;
}
//Install the class's embedded settings on the nodes in this node container.
ns3::NetDeviceContainer BaseWifi::Install(ns3::NodeContainer &nc) {
return m_wifiHelper.Install(m_wifiPhyHelper, m_wifiMacHelper, nc);
}
I have run into these kind of issues before. Apparently the initialization of static member objects very much depends on where the implementation is done in your code and (probably) on how the whole thing is compiled. The solution that I found (somewhere) to the problem was to wrap the whole thing into a static member function like this:
//in Agent.h
class Agent : public ns3::Object{
private:
//...
static BaseWifi& m_wifi();
//...
};
and:
//in Agent.cpp
BaseWifi& Agent::m_wifi() {
static BaseWifi TheObject=BaseWifi();
return TheObject;
}
This way the object is initialized properly the first time the static member function is called.
The difference here is the first approach is using copy constructor to initialize the object while the second is using the default constructor.

Calling function to return private variable from class not working

So I am making a small game in C++ and I have run across a problem. I have a class called player inside my player.h file, and inside this class I have a public function called getPotion(). I also have a private static variable called potion. I have the exact same thing for the players health, and the getHealth() function returns the private static int playerHealth perfectly. But for apparently no reason, the getPotion function doesn't return the potion. I get an error instead. I've also included the header file in all my other files.
Here's the code:
(Sorry, I don't know how to insert code, so I have to write it out)
player.h (the code that I'm having trouble with):
class Player{
private:
static int potions;
public:
int getPotions();
}
player.cpp (again the code I have trouble with):
int Player::potions;
int Player::getPotions(){
Player player;
return player.potions;
}
I have probably left out some bits of code like return and such, but that's because I have a small amount of time to ask this question, so I put the parts that related to my problem.
First off, you are trying to return a static member of a class as if it were instantiated member of the object. Static members are referred to by Class::member, not object.member.
Second, I don't think you want potions to be static. Static members are shared between all objects of the class. So if player A has 100 health potions, then player B would have the same 100 health potions.
Third, you declare Player::potions at the top of your .cpp file. I don't think that's what you want. The potions member was already declared in your .h file.
player.h:
class Player
{
private:
int potions;
public:
int getPotions();
};
player.cpp:
int Player::getPotions()
{
return potions;
}
If you DID want potions to be static, then change it to:
return Player::potions;
Try changing
Player player;
return player.potions;
to simply
return potions;
You're creating a new player and returning that object's potions, not the potions of the "this" object.