Changing integers in classes C++ - c++

Okay, so, I am storing a public integer in a class, like this:
class varglobalness{
public:
int xp;
int lvl;
int xpt;
int hp;
};
and, inside of a function I am trying to change the variables by doing this:
v.lvl += 1;
v.xpt += rand()%25+25;
v.xp = 0;
v.hp += rand()%25+5;
When I do this, though, hp doesn't change, xp does change to 0, but xpt and lvl changes to a lot of random numbers.
Any idea how I can properly change these integers without this happening?

Sounds like you're not properly initialising them. If a variable is uninitialised, it'll have an undefined value. You can give them initial values in the constructor:
// varglobalness.h:
class varglobalness {
public:
varglobalness();
// ...
};
// varglobalness.cpp:
varglobalness::varglobalness() : xp(0), lvl(0), xpt(0), hp(0) {}
Or assign them initial values elsewhere, as you prefer. As an aside, you ought to be putting these variables somewhere meaningful and encapsulated, rather than in a bundle of random globals.

Did you initialize the variables? Variables in C++ don't initialize themselves.
//In your constructor
v.lvl = 1;
v.xpt = 0;
v.xp = 0;
v.hp = 0;

Related

Problems in accessing variables in nested classes

I am trying to access the variable i declare in my nested class, but i fail to get the answer i want at the console. The result i want is 100, but all that i get is a long number. I cannot seem to find the error. This is what i wrote:
#include <iostream>
using namespace std;
class shpia {
public:
int tot;
class dhoma1 {
public:
int gjatesi;
int di() {
return gjatesi * gjatesi;
}
};
dhoma1 dh1;
void redi(){
cout<<dh1.di();
}
};
int main()
{
shpia::dhoma1 k;
k.gjatesi = 10;
shpia r;
r.redi();
return 0;
}
There's nothing surprising about your result. You seem to think
shpia::dhoma1 k;
k.gjatesi=10;
will define a dhoma1 for all shpia objects you will create. This is wrong. You just defined a shpia::dhoma1 object that has nothing to do with shpia objects.
When you then define
shpia r;
this will create in r another dhoma1, unrelated to the first one, which is not initialized. Hence when you print the square you're getting non-sense.
You are accessing uninitialized memory.
Here you create an instance of the nested class, and initialize its member:
shpia::dhoma1 k;
k.gjatesi=10;
And here you create an instance of the main class, which has nothing to do with the k. It already has a nested class member variable defined itself (r.dh1)
shpia r;
r.redi();
return 0;
Because of this new declaration, the nested class of r has no defined value and when you call redi(), you will access undefined memory and therefore get some random number. Depending on the actual runtime layout of your application, this value can change. It is undefined and you have to define it before you use it.
To fix this, you should use the nested class member of the main class instead, like this:
shpia r;
r.dh1.gjatesi = 10;
r.redi();
return 0;

Initializing an array outside class after declaration

For example:
const int m = 10;
class C{
public:
double A[m];
};
int main(){
C name;
name.A[m] = ... // initializing here?
}
I can't find a way around that, I could for example do
C name = {...};
Which would perfectly work but for the sake of functionality I wanna know if I can do that for single variables inside the class.
In your example, you only need to write:
name.A[x]=value;
Where value is double and x is between 0 and 9. You can also make a loop if you wish to set values for all or some of its elements.

C++ how to display multidimentional array in OO design

Hi I'm writing a simple version of Pacman with OO design in C++. I have problem displaying the content of a 2D array. The array constains a bunch of symbols, which represent the wall of the map/maze. Here is the sample code that I wrote:
Game.h
class Game
{
private:
char map;
public:
Game();
void displayMap();
};
Game.cpp
char map[10][20] = {...};
void Game::displayMap()
{
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 20; j++)
{
cout << map[i][j] << " ";
}
cout << endl;
}
}
The compiler will pop out an error at [i] saying "expression must have pointer-to-object type".
But if I define the size of the array in the header file and assign its value when defining the constructor
Game.h
class Game
{
private:
char map[10][20];
};
Game.cpp
Game::Game()
{
char map[10][20] = {...};
}
It will compile but when I try to display the content of the array (using the same code of displayMap()), I found out it's filled with junk. I think it's because that assignment is not an assignment. It's actually an initialization of another array on the stack, so that array is destroyed after the constructor finishes, and the displayMap() at that time display the original unassigned array.
I could be wrong, so feel free to correct me. I need a recommendation on how should I structure my game to avoid this problem
Game::Game() {
char map[10][20] = {...};
}
Here you redeclare a local variable with the same name of the instance variable, hence you hide the outer one. In addition you are trying to assign to an array which has been declared before, that's not possible in C++. You can just initialise an array when you declare it, not afterwards.
You can do this (if you have C++11 support):
class Game {
char map[W][H] = { ... };
}
or you can do this:
class Game {
char map[W][H];
Game() {
char tmp[W][H] = { ... };
memcpy(map, tmp, sizeof(char)*W*H);
}
}
Even better, you can use std::copy. Or even even better just use an std::array and forget normal arrays.
I commented your question, but I think it would be good to make it an answer, so here it is.
The second option should work fine.
Garbage values are normal in C/C++.
What you have to do is to initialize your values inside your constructor ( Game::Game() ). Constructors are meant to be used in these cases.
The behavior of C/C++ is to not assign a default value, it just "takes what's in place in RAM". Other languages do initialize the RAM cells though. It all depends of what programming language you are using.
Including this code inside your constructor (before accessing map[][] for another thing) should work:
for (int ix = 0; ix < 10; ix++)
for (int jx = 0; jx < 20; jx++)
map[ix][jx] = "x"; // x will be your default value

Working with objectives and calling methods?

I've probably become a bit to used to Java and am finding this harder than it should be. Heres what I have.
myObject[0] = new item1(this);
class item1
{
private:
int x;
int y;
public:
item1( passedPointer* pOne )
{
x = 5;
y = 5;
}
int returnX() { return x; }
int returnY() { return y; }
}
Then in another method I thought I could just say:
void check()
{
int y = item1.returnY();
int x = item1.returnX();
}
But I am getting the common error: a nonstatic member reference must be relative to a specific object.
There is only one instance of this class item1, what would be the best way to do this? This is just a simplified fragment of what I'm actually doing, not the actual code.
Item1 is a class. You have to create an instance of it before you can access its non-static members. Try looking here for some basic information.
void check(){
int y = item1.returnY;
int x = item1.returnX;
}
This would also be incorrect in Java, since neither returnX nor returnY are statics, you need an object on which to apply the operation, and you also need the parenthesis of the method call:
void check() {
item1 i;
int y = i.returnY();
int x = i.returnX();
}
Perhaps implementing the Singleton pattern would not do you harm, since you want only one instance of the object. You could declare the object as global or static to a function too, then get the values.
Then again, you could also declare the functions as static, and add another one to initialize the static values of the variables which need to be returned by those methods. There are a lot of solutions to this depending on your situation which can not be fully grasped by the short amount of code you have pasted.
You created an instance of class item1 with the line
myObject[0] = new item1(this);
Unlike JAVA, in C++ there are pointers and new returns a pointer to the object (so myObject[0] is a pointer to the instance) so you need the -> operator. To activate the method you should write:
myObject[0]->returnX();
If you wish to have only one instance than implement the class as a singleton.

Is it possible to pass a variable out of a class without creating a new object in C++

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.