I'm new to C++ and having a bit of trouble with accessing variables inside a class. From what I've read on here so far creating globals is a really bad practice and not to do that, but I dont know how else to move access to a class around.
So far my searches have pointed me to set and get functions in the class, but I think I can only use them in the block where the object is defined.
Basically what I want to know is if I define a class object in main() then call a function in main like gameLoop() how do I access that object inside that new function without making the class object global.
For instance:
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <string>
class Word
{
private:
string m_word;
int m_length;
public:
void set(string word, int length)
{
m_word = word;
m_length = length;
}
};
void gameLoop()
{
word1.set(); //flags error as it cant acces the word1 object
//I want to be able to access word1 from here
//Not a copy because that wouldnt change the actual word1
//I dont want to define it in here because then it would be created again
//for each loop of gameLoop
}
int main()
{
Word word1;
int play = 1;
while (play ==1){
gameLoop();
}
return 0;
}
This is a largely simplified version but for the purpose of the game I want the class to be stored externally but for a number of gameplay functions inside gameLoop to be able to access and change the class object.
Ideally, the dependencies of a function should be stater in the parameter list. If your gameLoop function requires a Word object, pass it in as an argument. That way, it's clear what objects the function requires to work. This would look something like:
void gameLoop(Word& word)
{
word.set();
// ^ Obviously you need to supply args here.
}
int main()
{
Word word1;
int play = 1;
while (play ==1){
gameLoop(word1);
}
return 0;
}
And since you're mutating the Word object in the function, you need to pass it by reference, or else you're just modifying a copy.
Your only other sane option would be to make the word object global, but that should be avoided at all costs. It makes testing more difficult since you need to take into consideration every change that may have happened, which makes it difficult to isolate problems.
If you're structuring you're program this way, you would have to pass it as a parameter to gameloop
However, This is a very poor design, since anything you create in main and want to access in gameloop would have to be passed in as an argument. I would consider a different approach.
You could move the entire loop and variable declarations into gameLoop as so:
void gameLoop()
{
Word word1;
int play = 1;
while (play ==1){
word1.set(/*args*/);
}
}
int main()
{
gameLoop();
return 0;
}
This way you won't have to pass a million things into gameloop. Generally in games there's some initialization and finalization that needs to take place as well, and this can all be done in main before/after the call to gameLoop.
So to answer you original question, you would have to pass word1 as an argument to gameLoop(). So redefine your function to accept a Word argument, and then pass in word1. but again, I would reconsider your current design before its too late
Related
Forgive me if the title isn't specific enough. Let's say I want to make an RPG. I make a class for the characters. I then make an array that function as a party of characters. Then I have a function that reduced the HP of the first member of a party.
`
#include <iostream>
#include <string>
class Chara
{
public:
int HP;
Chara(int health)
{
HP = health;
}
};
int Battle(Chara Party[2])
{
Party[0].HP -= 2;
}
int main()
{
Chara Final(0);
Chara Fantasy(7);
Chara Player[2] = {Final, Fantasy};
Battle(Player);
std::cout << Final.HP;
}
`
However, the HP of the character doesn't change. Is there something that I can do to make it so that the character's HP actually changes?
You have two separate problems caused by C++ passing structs by copy.
First, the line Chara Player[2] = {Final, Fantasy}; creates an array of Chara and initializes the members with copies of the mentioned variables. That means that the final line will not see any modifications made to elements of Player.
Instead, you should do:
Chara Player[2] = { Chara{0}, Chara{7} };
// and optionally, if you still want to access individual members:
Chara& Final = Player[0];
Chara& Fantasy = Player[1];
Secondly, you pass Player to the Battle function by copy. Thus, any changes made to Party inside the function are not reflected in the outer Player variable.
The quick fix is to take Party by pointer instead:
void Battle(Chara* Party) { ... }
This works because arrays can decay to pointers to their first element when passed.
As best practice, you should probably use a std::vector instead, which allows you to dynamically add and remove party members and has all kinds of helpful methods.
I am making a tictactoe game and would like the function for a player turn to access objects i declared in main and other functions how could i do that?
void Player1Turn::player1Turn() {
char num;
cin >> num;
if (num == '1')
{
board[0][0] = { xo1 };
}
For example how could i get board to change the values of gameboard?
int main()
{
Setup setup;
Gameboard gameboard;
Player1Turn player1turn;
setup.setup();
gameboard.printBoard();
player1turn.player1Turn();
return 0;
}
If this is not enough code I could provide more
You could add a reference to the specific Gameboard as an argument to the player1Turn member function. So, assuming your Gameboard class has a board[][] member, it would look something like this:
void Player1Turn::player1Turn(Gameboard& gb)
{
char num;
cin >> num;
if (num == '1')
{
gb.board[0][0] = { xo1 }; // Exact code will depend on your "Gameboard" definition.
}
}
And your call from main would be like this:
int main()
{
Setup setup;
Gameboard gameboard;
Player1Turn player1turn;
setup.setup();
gameboard.printBoard();
player1turn.player1Turn(gameboard); // Argument is the Gameboard to work on.
return 0;
}
There are many other ways to achieve this, though, but I can't really suggest anything more/better without more details of your various classes. Another way, as suggested in the comment by Nico Schertler, would be to have the reference to Gameboard as a "data" member in the Player1Turn class and pass the reference in its constructor.
Feel free to ask for further clarification and/or explanation.
PS: Your use of the three names, "Player1Turn" (for the class), "player1Turn" (for the member function) and "player1turn" (for the specific object in main) is extremely prone to typing errors! You should seriously consider a better naming scheme!!
I have a shape class that I initialize from my main program and give the parameters in the constructor.
Shape *cusomShape = new CustomShape(float radius, float origin)
The shape class has some functions such as rollover and more.
When the rollover function inside the shape class is fired, I want to change a certain int value in the main program. This might similar to firing of an event that changes the value when the rollover function is fired, but I am not sure how to do that in C++. If at all, events is the ideal approach here, it would great to see a short example coming.
If using the event is not the correct, what would the ideal way to go about this?
I think what you need is to pass a value by pointer or reference to the function in Shape and then modify it. If the function is called not from main but from somewhere else passing the pointer is the better option you have. First pass the pointer to the class and store it using another method and then each time rollover is called make use of it.
EDIT: example:
class CustomShape {
void storePointer(int* _value) {
value = _value;
}
void rollover() {
.. do stuff
*value++; // for instance
... do stuff
}
int * value;
}
int main() {
int a;
CustomShape cs;
cs.storePointer(&a);
....
cs.rollover();
....
return 0;
}
Pass a reference to the variable in the constructor and save that reference. Change the value when needed.
I would suggest passing a reference to the variable to the member function that needs to change its value. Storing a reference in a class couples the Shape class to the reference. This means that each time you want to use the Shape, without updating the integer, you cannot, since the Shape constructor will expect a reference/pointer to the int as an argument (the Shape class will store the pointer/reference as an attribute). Passing a reference/pointer to the member function promotes Low Coupling.
#include <iostream>
class Shape
{
double shapeValue_;
public:
Shape (double value)
:
shapeValue_(value)
{}
void fireFunction(int& updateMe)
{
updateMe = 123;
}
};
using namespace std;
int main()
{
int update;
cout << update << endl;
Shape s(4.5);
s.fireFunction(update);
cout << update << endl;
return 0;
};
And in this case, you have an option for a main program that doesn't involve shape object calling on fireFunction:
int main()
{
Shape s(4.5);
// Main program that doesn't use fireFunction.
return 0;
};
In this case, if you have member functions changing input arguments, you should take on a style for defining such functions: e.g. make sure that the variable that gets changed by the member function is always the first input argument in its declaration.
If you want complex objects to communicate updates between each other, you can make use of the Observer Pattern.
I have a variable, which is a member of one of my classes, that another is in need of, but I'm not sure how to effectively pass the value between them without using a global variable, which is something I'd like to avoid if at all possible. I know I could create an object, but that would invoke the constructor of the originating class which would execute a number of functions and write the needless results to memory, which would be wasteful of system resources.
Is there an easy way to pass this value between the two functions?
Update: The class that is in need of the variable, called no_of_existing_devices. The purpose of class Initialise is to open up a file and count the number of lines of test it contains, and place that number in the variable int no_of_existing_devices, which is then used by the Device::Device() to create an object for each
class Device
{
public:
void view_attribute_list();
void set_attribute();
Device();
};
Device::Device()
{
for (int count = 0; count < no_of_existing_devices; count ++)
{
// Create an object for each iteration, up to a maximum of no_of_existing_devices
}
}
The class of which this variable is a member
class Initialise
{
public:
int no_of_existing_devices;
bool initialisation;
string existing_device_list[100];
void initialise_existing_devices();
Initialise();
};
Initialise::Initialise()
{
no_of_existing_devices = 0;
}
void Initialise::initialise_existing_devices()
{
string line;
ifstream DeviceList;
DeviceList.open("devices/device_list");
while (true)
{
getline(DeviceList, line, '\n');
if (DeviceList.eof())
{
break;
}
++ no_of_existing_devices;
}
DeviceList.close();
DeviceList.open("devices/device_list");
for (int i = 0; i < no_of_existing_devices; i ++)
{
getline(DeviceList, line, '\n');
existing_device_list[i] = line;
}
Device existing_devices[no_of_existing_devices];
!initialisation; // Existing devices are now initialised
}
Okay, from what I understand:
You don't want to have a global
You don't want to have a static
You don't want to introduce a dependency between Device and Initialise
There is one other option, assuming something owns Device and Initialise, move the no_of_existing_devices up to there, then construct both Device and Initialise with a reference to this variable...
In a similar circumstance I was just passing the pointer to the member --- I had to invoke a member function then, so it was a pointer to the member function, http://www.parashift.com/c++-faq-lite/pointers-to-members.html
It's a bit messy, but it works :-).
If the variable in the originating class can hold a value without an instance of the class I would assume that the variable is static. If not create a public static member of the class. And use it in the target class.
Something like:
// .h file
class A
{
public:
static int a;
}
// .cpp file
int A::a = 123;
// .cpp file of class B
void B::foo()
{
cout << A::a;
}
If it is a class attribute (internal variable), then you can obtain a reference through a get method. Otherwise, you can use the friend keyword on the class you want to access the attribtue from the other For example, if you declare friend class B; on class A, the attributes of the class B will be accessible on the class A.
I suggest you use the first method in order to maintain your code OO pure ;)
Edit: of course, if you access through a reference there are no resources wasted :)
Edit 2: use a static method on Initialise class that returns the no_of_existing_devices and call Initialise::NoOfExistingDevices() on the Device class. If you want to resources use a pointer like this:
public static int* Initialise::NoOfExistingDevices() {
return &no_of_existing_devices;
}
By the way, I advise you to turn the variable private.
I need to write a program that prints 100 stars on the screen (at random places), and then the stars disappear slowly - one after another. I'm not allowed to use loops nor recursions.
I've tried to play with the constructors and the destructors but I can't get the stars to disappear one after another (and not all together).
Any ideas?
Thanks,
Li
Sorry - forgot to mention i'm using c++
My current access violating useless code:
class star {
int x;
int y;
public:
star(){
x = rand()%80;
y = rand()%80;
PaintcharOnRandomLocation('*',x,y);
};
~star(){
PaintcharOnRandomLocation(' ',x,y);
};
};
class printAll{
star* arr;
public:
printAll(){
arr = new star[100];
};
~printAll(){
delete[] arr;
};
};
void doNothing(printAll L){
};
void main()
{
srand ( time(NULL) );
doNothing(printAll());
getch();
};
Seems the only way possible without loops/recursion is something like this:
class Star
{
Star()
{
//constructor shows star in a a random place
}
~Star()
{
//destructor removes star and sleeps for a random amount of time
}
};
int main()
{
Star S[100];
}
This is really just a dumb trick because the compiler has to run the constructor for each star to initialise the array and then the destructor for EACH star as it goes out of scope.
It is also a bad trick as all the workings that go in the main function are opaque and invisible. It would obviously be better to use a loop in this context and putting the delay inside a destructor like this is really confusing and unmaintainable.
This is not a runtime recursion:
template<int N>
struct Star
{
Star() { DrawAtRandomPlace(); }
~Star() { RemoveSlowly(); }
Star<N-1> star;
};
template<> struct Star<0> {};
int main()
{
Star<100> stars;
}
The code above will generate 100 different instantiations of the Star template. RAII will guarantee the order of drawing and removing.
Based on your final comment, can you have the destructor of your star class do a delay? See for example the sleep or usleep functions.
Since Destructors/Constructors are only an Idea, they're probably not the right title for your question.
I don't know what system/environment you are in, but how about this:
Create a buffer that contains a string with your stars, simply manually by typing them in the code.
Next, write a function that displays the buffer to whatever output window you use.
Then, you would need a function that has a static(!) pointer to the back of the buffer, and that does the following:
Call the buffer printing function
Write a null byte under the current pointer position
Decrement the static pointer
Wait for a period of time
Raise a custom signal with raise()
In the main() function, you set the the Signal Handler for your custom signal to the function described above, and then you raise the custom signal.