Page 1 of 1

C++ Question with classes [SOLVED]

Posted: Sat Aug 06, 2011 10:04 pm
by DTKilb
Hello, I've been working on learning C++ and have been making my own small projects recently. I'm currently trying to make a small text based RPG using C++. In the process, I've been trying to use multiple files and classes for experience. So far, I've been doing things such as making a player file holding a class that contains all of the player's variables. Such as health,
playerLevel, gold, etc. I'd later make separate files that contain the game play for specific levels in the game. Such as a level1.h/level1.cpp. In the process, I've included the player file into the level1.cpp in order to get the players gold/level for reasons such as shops or combat. But whenever I try to make an object of the player class, such as "player p;" and try and, for an example, display the player's health "cout << p.health;" the value is completely different from what it is initialized to. My question is to what is causing this problem and how I can stop this from happening in the future.
Here is a quick example to make my situation more clear.

Main.cpp:

Code: Select all

#include <iostream>
#include "example1.h"
#include "example2.h"
using namespace std;

int main(){
	example1 ex1;
        example2 ex2;
	ex1.initVariables();	
	ex2.startLevel();
}
Example1.h:

Code: Select all

#include <iostream>
using namespace std;

class example1{
public:
	void initVariables();
	int playerHealth, playerGold;

};
Example1.cpp:

Code: Select all

#include <iostream>
#include "example1.h"
using namespace std;

void example1::initvariables(){
	playerHealth = 100;
	playerGold = 100;
}
Example2.h:

Code: Select all

#include <iostream>
using namespace std;

class example2{
public:
	void startLevel;
};
Example2.cpp:

Code: Select all

#include <iostream>
#include "example2.h"
#include "example1.h"
using namespace std;

void example2::startLevel(){
	example1 ex1;
	cout << "Your Health: " << ex1.playerHealth; //When displayed, this is NOT 100 (what it was initialized to)
	cout << "Your Finances: " << ex1.playerGold << " gold"; //Not what it was initialized too, either.

}

Re: C++ Question with classes

Posted: Sat Aug 06, 2011 10:41 pm
by JesseGuarascia
Well for starters, what you're doing is a mistake I made at first, too :P Variables have something called "scope" applied to them. Scope is kind of like a sniper scope. Different parts of your code can only see things that are in their scope. The main function in main.cpp has the variable ex1 in it's scope at all times. In your main.cpp, you have your main function where you declare the first ex1 variable, putting it into the main functions "scope". There's global and local scope: Global means all functions that know that variables name (have it included or declared outside of all functions). Local means that the variable is created inside of the function, meaning that only that function has access to the variable. So with the idea that each function can only see variables it's given scope to, look at your second class' startLevel function:

Code: Select all

#include <iostream>
#include "example2.h"
#include "example1.h"
using namespace std;

void example2::startLevel(){
   example1 ex1;
   cout << "Your Health: " << ex1.playerHealth; //When displayed, this is NOT 100 (what it was initialized to)
   cout << "Your Finances: " << ex1.playerGold << " gold"; //Not what it was initialized too, either.

}
By creating a new ex1 of the type example1, you're not accessing the same variable declared in your main function. The ex1 in example2's startLevel function is local to that function, and ex1 of the type example1 in main.cpp's main function can only be seen by the main function. In order to have access to the variable ex1 that you initialized in the main function, you'd have to make that variable completely global. Here's my suggestion for a beginner:

Create a file that has the variable globally.

Player.h:

Code: Select all

#ifndef PLAYER_H_
#define PLAYER_H_

#include "example1.h"
extern example1 ex1;

#endif // PLAYER_H_
Player.cpp:

Code: Select all

#include "Player.h"

example1 ex1;
This is HORRIBLE practice, but since you're just a beginner with classes, I'm not going to get into polymorphism and inheritance and manager classes. Lemme know if this works out for you, or if you have any other questions :)

Re: C++ Question with classes

Posted: Sat Aug 06, 2011 11:18 pm
by DTKilb
Thank you so much for your help!
Also, I've noticed something that I've run into a lot online, where people place in arguments with their functions with things such as:

Code: Select all

void example1(example2& ex1){ }
Could that have anything to do with my issue in any way?

Re: C++ Question with classes

Posted: Sat Aug 06, 2011 11:32 pm
by JesseGuarascia
All this is, is a function who has an argument that is a reference :) A reference is almost a complete copy of a variable, but it has the exact same memory address. It's sort of like taking a variable and momentarily moving it somewhere else, only to move it back once it's done what it needs to do. That's another great way of giving the information, but I wasn't sure to what extent you understood things like that. :P I didn't want to go an suggest something I wasn't sure you knew or not :)

If you were to use references in your example, all you would have to do is change your startLevel function to something like this:

Example2.h:

Code: Select all

class example2{
public:
    void startLevel(example1 &ex1);
}
Example2.cpp:

Code: Select all

void example2::startLevel(example1 &ex1){
   cout << "Your Health: " << ex1.playerHealth; //When displayed, this is NOT 100 (what it was initialized to)
   cout << "Your Finances: " << ex1.playerGold << " gold"; //Not what it was initialized too, either.
}
From the example code you gave for the function, though, you wouldn't need to use a reference. Just make the same changes, but don't put the ampersand (&). Either way should work fine :)

Re: C++ Question with classes

Posted: Sun Aug 07, 2011 1:28 pm
by short
A reference is almost a complete copy of a variable,
No.... just....... no.....

A reference is a just that, a reference. If you make changes to a reference inside an object, when your return from the function the object you passed a reference of has still been modified. It's because your only ever working with one object, there are no copies when passing by reference. When you pass a reference to a function, its just a memory address.

Re: C++ Question with classes

Posted: Sun Aug 07, 2011 5:49 pm
by ibly31
@short
I thought that that's what pointers did. Like I thought if you wanted to modify an object, you passed by pointer, not reference. I'm so confused by C++'s memory stuff, thats why I use ObjC :)

Re: C++ Question with classes

Posted: Sun Aug 07, 2011 9:30 pm
by JesseGuarascia
short wrote:
A reference is almost a complete copy of a variable,
No.... just....... no.....

A reference is a just that, a reference. If you make changes to a reference inside an object, when your return from the function the object you passed a reference of has still been modified. It's because your only ever working with one object, there are no copies when passing by reference. When you pass a reference to a function, its just a memory address.
So clearly, you read that part of that one sentence and decided to write a response.
JesseGuarascia wrote: A reference is almost a complete copy of a variable, but with the exact same memory address. It's sort of like taking a variable and momentarily moving it somewhere else, only to move it back once it's done what it needs to do.

Re: C++ Question with classes

Posted: Sun Aug 07, 2011 10:27 pm
by short
So clearly, you read that part of that one sentence and decided to write a response.
Reading the word copy was enough (of course I read your whole post). Sorry if it sounded rude.
A reference is almost a complete copy of a variable, but with the exact same memory address. It's sort of like taking a variable and momentarily moving it somewhere else, only to move it back once it's done what it needs to do.
This explanation is weird (to me) because there is no moving done what-so-ever, and I thought it help both of you to consider exactly what a reference does, not talk about it in terms of moving things and making copies when neither is done.

A pointer is similar to a reference, but having a pointer to an object allows you to do operations "on the pointer" such as addition (visit each element of an array). The reference is like having a constant pointer (that the only operation you can do is de-referencing), you can't do any operations on the pointer itself, because, well it's constant. You can operate on a reference with the . notation, (as opposed to de-referencing a pointer with the -> operator). Yes Ibly, pointers and references are very similar, when working at this level of programming.


An extremely strong/easy to understand example is consider that Java C# passes all objects by reference.
(please ignore that you generally cannot define a function within another function, like I do below, in all 3 examples)
C# code

Code: Select all

Object j = new Object();
j.arg1 = 100;
Whatevs(j);

void Whatevs(object j) {
    j.arg1 = 35;
}

println(j.arg1);
output: 35;
Since C# passed in j by reference (ie j's memory address) to Whatevs, j could modify j directly. Thus later when j.arg1 was printed in the calling function scope, j's value had been modified to 35.

Consider the same example in C++ which passes all values/types by COPY (by default)

Code: Select all

Object *j = new Object();
j->arg1 = 100;
Whatevs(*j);

// by passing in j to Whatevs(), a copy of j is made and given to Whatevs() to operate on.
void Whatevs(object j) {
    j.arg1 = 35;
}
println(j.arg1);
delete j;
Thus is it obvious the output is 100;

To get the same effect as the c# model of passing objects (by reference) we simply use the & syntax.

Code: Select all

Object *j = new Object();
j->arg1 = 100;

// all changes made to j inside Whatevs will persist, as no copy is made. We are passing Whatevs the memory address j is stored at in memory, so it can modify the object directly in memory.

Whatevs(*j); // this will still passed by reference
// or we can declare a local j, modify its arg1, and pass by reference 
Object k;
k.arg1 = 100;
Whatevs(k);

void Whatevs(object &j) {
    j.arg1 = 35; // notice . syntax
}

println(j->arg1);
delete j;
println(k.arg1);
output: 35
and
output: 35;
I hope this is more clear. JesseGuarascia I didn't mean to be rude, I apologize.

Re: C++ Question with classes

Posted: Mon Aug 08, 2011 3:35 pm
by Falco Girgis
JesseGuarascia wrote: A reference is almost a complete copy of a variable, but with the exact same memory address. It's sort of like taking a variable and momentarily moving it somewhere else, only to move it back once it's done what it needs to do.
This is a contradiction by definition. "Copy" and "same memory address" are not compatible. It's nothing at all like taking a variable and moving it.

A C++ reference is LITERALLY an auto-dereferenced C pointer. If you look at any disassembly, they are equivalent behind the scenes. The C++ syntax spares you from having to pass memory addresses around and use pointer indirection, but it is literally doing the same thing.

Re: C++ Question with classes

Posted: Thu Aug 18, 2011 6:57 pm
by Pornomag
ibly31 wrote:@short
I thought that that's what pointers did. Like I thought if you wanted to modify an object, you passed by pointer, not reference. I'm so confused by C++'s memory stuff, thats why I use ObjC :)
That's why you use Objective-C? What the hell?! Objective-C has pointers (I'm not sure about references, but a reference is a pointer in some term). Objective-C is a strict super set of C.

If anything Objective-C memory management is harder, every object of a class you make has to be a pointer and if you want to use it you have to usually call alloc, new or copy. And then it has to call release sometime later in your program unless it's an autorelease object.

Re: C++ Question with classes

Posted: Thu Aug 18, 2011 7:16 pm
by Pornomag
Oh and here's a quick overview of what you should do in classes. To initialise variables when you create an object you use a constructor and an initialiser list when possible. If however you don't want to initialise variables as soon as the Object of your class is create you can set them manually. Another note is to always try and keep your variables PRIVATE, therefore no one can touch them and play around with them directly. You use getters/setters to set and get your variables, but if it's a pointer if you create a getter then someone can indirectly modify your private data with ease. Here is an example of what a class usually should be like.

Code: Select all

class Example{
private:
      int x;
public:
// Default constructor that initialises x to 0
      Example()
      : x(0) // Same as saying x = 0*
      {
      }
// A custom constructor that initialises x to a custom value
     Example(int value)
     : x(value) // Same as saying x = value*
     {
     }
// Some getters and setters
     int getX() const { return x; } 
/*
The const keyword after the function 
tells the compiler that no variables are 
modified and can be used with a const Object of this class
*/
     void setX(int value) { x = value; }
};
Notes:
In your class it is good programming practice to not access the private data directly, you should use your getter/setter function.
Another note is that, when you define the body of a function inside your class, the function is usually implicitly inlined for you, depending on your compiler/settings and if it can be inlined.
*You could set x to those values in the body of the constructor, but a initialiser list initialises the variables before the body is reached.

You should read more about classes in a book or some websites, I really recommend a book because it will be more informative because they get payed for writing a whole book. But you could also check this website about learning C++: http://www.cplusplus.com/doc/
And seeing as your learning classes here's the direct links for the articles about classes in C++
http://www.cplusplus.com/doc/tutorial/classes/
http://www.cplusplus.com/doc/tutorial/classes2/