Archived

This topic is now archived and is closed to further replies.

Peon

Classes, and the "correct" way to access private variables

Recommended Posts

Peon    276
Hey all I''m still working on my GDI "Tank Wars" type game, and am going with an object oriented approach. One problem I''ve been having is how I should be accessing private memeber variables. For example, each tank has variables such as position, current angle, current weapon, hull strength, etc... and each of these is a private variable. However, other functions (such as the outputting to screen what the angle is) need to know the value of these variables. This has caused me to have to add several acessor functions to my TankClass... queryAngle(), queryPosition(), etc... Just wondering, is there a more efficient or correct way of doing this? It seems kind of overkill Thanks in advance! Peon

Share this post


Link to post
Share on other sites
myme15    122
If the tank stores all the angle, weapon, and hull strength data, it should probably be in charge of displaying it all itself. I'm no OOP expert, but I think if you encapsulate ALL the tank-related functionality in the tank class, then you'll have no need for all those accessors.

It seems to me that having a lot of outside functions access private members through accessors defeats the purpose of making them private in the first place. If they're private, things outside the class should not have to know about them.




Things are not what they are.


[edited by - myme15 on June 9, 2002 6:26:33 PM]

Share this post


Link to post
Share on other sites
iwasbiggs    122
Depends on your personal style. You could make a member function embedded with the tank class that takes in a screen or HDC class, for example, and then draws to it, using it''s own access to the private variables. However, if you want some cross platform action, this may sorta prevent that. If you have a screen, or rendering class/function, you could make that class/function a friend of the tank''s class, that would give the rendering class complete access to private variables, but most people don''t like doing that, because it breaks encapsulation.

So it depends on whether or not the code''s going to be reused, if other people will be using it, personal preference, etc...

If you have the query methods inline, that''d technically, be the best way, allowing others to read those variables and with speed. But doing all those query methods does require more coding.

Share this post


Link to post
Share on other sites
IndirectX    122
It depends on how much TankClass is a self-contained object. If it primarily consists of data members that other classes manipulate, then you may be better off making it a struct will public data. A few public helper methods will be acceptable as well. If, however, your tank handles a significant amount of work needed to handle movement, displaying, collisions and so on, then make data members private and provide accessors.

Share this post


Link to post
Share on other sites
Peon    276
Thanks for the help guys The reason I want to access the variables and not have the tank display it is because, well, I don''t know if a tank should be displaying anything. Hence, I created a "taskBar" class to take care of that. Perhaps this is not the best way to do it, hehe.

Another thing I was thinking of (and I think someone mentioned it above) would be to have a struct, called, say, tankStats that would be private, andthe advantage to this would be that I need only one query function to use it. As of right now, I''m querying for power/angle/etc seperately, which seems like a real waste. Are there any disadvantages to doing it this way (using a struct with all the data)?

Thanks again

Share this post


Link to post
Share on other sites
iwasbiggs    122
nah, using a struct should be fine, it would be a good idea to return the data struct by const reference, unless your taskBar class actually needs to modify the tank variables.

Share this post


Link to post
Share on other sites
Peon    276
quote:
it would be a good idea to return the data struct by const reference, unless your taskBar class actually needs to modify the tank variables.


Thanks for your reply, once again! Just to clarify what you mean here... I would so this using pointers and such correct (sorry, don''t have enough experience with them, and want to make sure I''m trying to do the right thing )? If I''m understanding correctly, this would be like being able to determine what the values of the struct variables are, without having to return an actual struct?

If so, I think this would be ideal for communication bewteen several of my classes, since they need to interact with one another.

Share this post


Link to post
Share on other sites
Ziphnor    122
You should keep the accesors. They allow you to change the inner working of the tank class and still work with the outside.(for example, you might change the way the position is stored)
Furthermore set/get methods allow you to control the state the tank is put into. If the members are public someone might set its hitpoints to -10 which might be an invalid value(okay, it might not be too serious in this simple case). With a setHP-method you can disallow this behavior(either raising an error or just ignoring the command, keeping the tank instance in a valid state).
Stick with the get/set methods, just inline them.

Share this post


Link to post
Share on other sites
CaptainJester    523
The standard OOP approach is to keep data variables private and create accessors for them all. However, whoever said a game is standard. That way of designing things is useful in apps where the lifetime of the app is large, ie Microsoft Word, and you want to keep reusing components without rewriting the whole shebang. In game programming, there is less need for this, especially if you are the only one working on the project. Most game systems get rewritten in the next iteration anyway. So, until you learn the ins and outs of making a game engine, just concentrate on making your game work, then later on with some experience under your belt you will be able to see yourself some areas that require encapsulation and other areas don''t.

---
Make it work.
Make it fast.

"Commmmpuuuuterrrr.." --Scotty Star Trek IV:The Voyage Home

Share this post


Link to post
Share on other sites
MrBeaner    144
Why not just make the tank a complete package, and when a function needs to know how the tank is doing, it sends a message to the tank and says "hey, whats up?" then the tank says "well, in this past loop i died, so sorry." or it says "The last time around i took a beating, but i just updated everything, so keep rollin'."

This is why you would want to create a class. Then, if you create a file (for example tank.h) you can reuse it in future code projects, or update it as necessary. all functionality of the tank class resides in the tank class. Your program just wants to know certian things from it, but doesn't rely on data in the class to make calculations unique to the tank. The tank does this.

Do you think Generals in the field command every aspect of every tank that they send out? Of course not. They send out a tank "package" and tell them to take out a building. The tank "package" worries about the details. Then later they send a message to this tank "package" askng how everything is going, or their current position.

This makes everything really easy. In fact, you could have an accessor function called tank::update() which would just update everything.

NOW....

This is cool if you plan on making a whole entourage of tank objects. But if you have two objects on the screen, then maybe a struct is much better. But think about this: how cool would it be if you encapsulated the tank AI code in the tank class, so when you called tank::update(), it updates it's own position based on some certain values? then when you are ready to draw to the screen, you just obtain the tanks new position calling tank:: Position()?

[edited by - MrBeaner on June 11, 2002 1:54:07 PM]

Share this post


Link to post
Share on other sites
JWalsh    498
Heya all,

As a fairly experienced OO programmer I just thought I'd share some of my revelations.

Basically, accessor functions are good for two things.

1. If you plan on changing the way the internals work often.
2. There is more happening than might be immediately obvious, that is there is "extra" functionality.

Here's an example.


struct CSquare
{
float height;
float width;
float area;
};



In the above example you have three fields, but you'll notice that one of them is based solely upon the other two. This would be an example of when accessor functions would be GOOD. It is a demonstration of rule #2 above...continuing the example:


CSquare square1;
square1.height = 10;
square1.width = 10;
square1.area = 100;

// if now at a later time I do the following,
// without changing the area field, I've got a problem
square1.width = 5;


The better solution is to put the height and width into set/get functions, even though they seem redundent...it prevents stupid mistakes.

One last example...suppose I have the following class.

Class CPoint2D
{
public:
float GetX();
float GetY();
SetX(float arg);
SetY(float arg);

private:
float x, y;
};


The above is an obvious example of when NOT to use set/get functions. The reason being is because there is no "extra" calculations going on by setting either x or y, and even more than that...the functionality of a 2D point will most likely NEVER change.

If you follow the 2 rules above, you should find that public vs. private becomes a bit more obvious.

Best Regards,
Jeromy "Maverick" Walsh
------------------------
"The question isn't how far, the question is do you possess the constitution, the depth of faith, to go as far as is needed?" -Boondock Saints

[edited by - jwalsh on June 11, 2002 3:35:43 PM]

Share this post


Link to post
Share on other sites
hpotter2    122
Excuse me if this is repetitious(i only read the question), but there is a basic solution: make the tank data public, not private.

Share this post


Link to post
Share on other sites