Archived

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

Mike737

Static variables in classes

Recommended Posts

Mike737    122
I have noticed that in C++ when using a class if you use a static variable (encapsulated inside the class), that the same static variable will be shared across all instances of this class. eg. SampleClass Test1; SampleClass Test2; void SampleClass::SampleClass() { static int test; printf("Static addressed @ %p\n",&test); } When using the piece of code above I recieve the output of: Static addressed @ 0045B8CC Static addressed @ 0045B8CC So my problem is how do I get around this? Or is this a bug in C++ (im using the MSVC6 compiler)? Thanks Extracting Patch.... Initializing Windows XP Update Path 2543663B.... Core Dumped, Now Installing Linux..... ---- Mike Team AI: Http://members.iinet.net.au/~slyons/teamai

Share this post


Link to post
Share on other sites
theSeby    122
You can declare a static variable in a constructor, but in the class definition.


class MyClass
{
public :
static int test;
...
};
...
MyClass::MyClass(...)
{
test=5;
...
}


------------------------
- Seby -
www.dfhi-bomber.fr.st

[edited by - theSeby on August 8, 2003 3:23:44 AM]

Share this post


Link to post
Share on other sites
Mike737    122
Is there any other possible ways?

I hate doing things such as that because it doesn''t really conform to OO Design. But then again C++ isnt really a full implemented OO language.



Extracting Patch....
Initializing Windows XP Update Path 2543663B....
Core Dumped, Now Installing Linux.....

----
Mike
Team AI: Http://members.iinet.net.au/~slyons/teamai

Share this post


Link to post
Share on other sites
BitMaster    8651
quote:
Original post by Mike737
I have noticed that in C++ when using a class if you use a static variable (encapsulated inside the class), that the same static variable will be shared across all instances of this class.


Er... this is exactly what static inside a class is supposed to do.

Share this post


Link to post
Share on other sites
hammerstein_02    134
How exactly do you want to get around this? You use a static variable for the exact reason you mentioned, to share an a variable across all instances of a class. Are you actually looking for a solution whereby each instance of a class is aware of the other one in someway?

Share this post


Link to post
Share on other sites
Mike737    122
quote:
Original post by BitMaster
Er... this is exactly what static inside a class is supposed to do.


Oh?! When using VB static variables are actually not shared... they are relative to that particular instance of that class so SampleClass1 = 1 while SampleClass2 = 2.


I''m using static variables for a number of functions, but the main concerning one is that I have several functions inside my class which keep the last time that that particular function was called. Then I check whether enough time has elapsed for me to do an update on that function. There are about 100 instances of the 1 particular class running as it is my bot class.

So I guessing that I''m gonna have to bite the bullet and put them in the class declaration?

Extracting Patch....
Initializing Windows XP Update Path 2543663B....
Core Dumped, Now Installing Linux.....

----
Mike
Team AI: Http://members.iinet.net.au/~slyons/teamai

Share this post


Link to post
Share on other sites
smart_idiot    1298
I think you are looking for something like this:


#include <iostream>

class foo
{
public:
foo(): my_id(++count)
{
std::cout << "I am instance " << my_id << "." << std::endl;
}
int my_id;
static int count;
}
foo::count = 0;

foo foo1, foo2, foo3;

Share this post


Link to post
Share on other sites
drekkar    122
it''s not a bug, a static variable sticks with what it is supposed to. if you want a specific variable for a class what''s wrong with members?

Share this post


Link to post
Share on other sites
Wildfire    154

// MyClass.h File:

class MyClass
{
static long test;
};

// MyClass.cpp File:

long MyClass::test =0;



Maybe you mean this:

class MyClass
{
void function (void);
}

void MyClass:function(void)
{
static access=0;

std::cout << "I have been accessed " << ++access << " times";
}

Now the static is not shared between the instances. Access will be set to 0 when function is called for the first time, after that this line is ignored (This is only valid for variable=0 I think).

You don''t need to use static for that in any case though, that''s the nice thing about a class.

class MyClass
{
long functionCounter;

void function (void);
}

void MyClass::function(void)
{
++functionCounter;
}

Share this post


Link to post
Share on other sites
Mike737    122
quote:
Original post by drekkar
it''s not a bug, a static variable sticks with what it is supposed to. if you want a specific variable for a class what''s wrong with members?


I guess I think I''m just going to have to.

The only reason why I don''t want to is because I have so many of these and they are function specific and only used in that one function - hence the reason for encapsulating them inside the functions.

I know I am being a bit picky but I hate other functions being able to gain access to other functions variables. But my theory comes down to why should you let your talk() function have the ability to alter/control your moveFoot() function in the person class?


Thanks for all your help so far guys

Extracting Patch....
Initializing Windows XP Update Path 2543663B....
Core Dumped, Now Installing Linux.....

----
Mike
Team AI: Http://members.iinet.net.au/~slyons/teamai

Share this post


Link to post
Share on other sites
Wildfire    154
quote:

know I am being a bit picky but I hate other functions being able to gain access to other functions variables. But my theory comes down to why should you let your talk() function have the ability to alter/control your moveFoot() function in the person class?


I think you''re taking encapsulation a bit far. As long as you are writing the class, you don''t have to hide data from yourself? It''s like writing a private iterface for accessing your private data... Unless you can''t remember that talk() shouldn''t alter any foot values, I don''t see any reason why you should be accidently doing it?

A function can''t access another functions variables. Member-functions can access variables of your class, but not other member functions variables.

And, like I mentioned in my above post, if you make the static variable part of the function, it''s accessible for that one member function only.

Share this post


Link to post
Share on other sites
Mike737    122
quote:
Original post by Wildfire
I think you''re taking encapsulation a bit far. As long as you are writing the class, you don''t have to hide data from yourself? It''s like writing a private iterface for accessing your private data... Unless you can''t remember that talk() shouldn''t alter any foot values, I don''t see any reason why you should be accidently doing it?


I understand I was taking it a little bit to far, but as I said I am being picky.

quote:

And, like I mentioned in my above post, if you make the static variable part of the function, it''s accessible for that one member function only.


Well I will give you a quick example of my class so you can understand more what I am talking about:


class Agent
{
public:
Agent();
virtual ~Agent();

float getX();
float getY();
int getHeading();
void setXY(int iX, int iY);
void setHeading(int iHeading);
void moveXY(int iX, int iY);
void setID(int iID);

bool getControllable();
void setControllable(bool bControl);

void update();

LOS *getLOS();
AStar *getAStar();
AgentCoverMap *getCoverMap();
void setDataMap(DataMap *CDataMap);
void go();

enum MovementSpeed getMovementSpeed();
void setMovementSpeed(enum MovementSpeed eSpeed);

int getState();
char *getStateName();

private:

void updateState();
void updateMovement();
void findNearestCover();

bool m_bHControl;

AgentCoverMap m_CCover;

float m_fX;
float m_fY;
int m_iHeading;
//int m_iHealth;

LOS m_CLOS;
AStar *m_CAStar;
DataMap *m_CDataMap;

int m_iID;
int m_iState;

enum MovementSpeed m_eMotionSpeed;

Weapon m_CSelectedWeapon;

};

void Agent::updateMovement()
{
static AList::iterator CNode;
static AList::iterator CDebugNode;
AList::iterator CPreviousNode;
static bool bFirstMove;
static bool bAtDestination=true;
static long lNextMoveTick;
static bool bNextMove=true;
static bool bFinalMove;
static int iMoveX, iMoveY;
static float fMovingX, fMovingY;
static float fSpeedX,fSpeedY;
long lTimeLimit;
bool bEnd;
int iErrorLoop=0;

//update pathfinding
if ((!m_CAStar->pathFound()) && (!m_CAStar->faultOccured())) //check if astar needs to be calculated
{
lTimeLimit = (long)GetTickCount() + 50;

//run until AStar runs out of time
do
{
m_CAStar->update();

//check for fault or path found
if (m_CAStar->faultOccured() || m_CAStar->pathFound())
break;

}while (lTimeLimit > (long)GetTickCount());

bFirstMove = true;

if (m_CAStar->pathFound())
{
bAtDestination=false;
lNextMoveTick = GetTickCount();
bNextMove = true;
bFinalMove = false;

//setup first node
CNode = m_CAStar->getPath()->begin();
}
}

if (m_CAStar->pathFound())
{
//move along path
if ((!bAtDestination) && (lNextMoveTick {

if (bNextMove)
{

//get next node
bEnd = false;

do
{
//check if no nodes exist on list
if (m_CAStar->getPath()->size() == 0)
{
bAtDestination=true;
return;
}

//grab new and previous node and remove previous from list
CPreviousNode = CNode;
++CNode;
m_CAStar->getPath()->remove(*CPreviousNode);

//check if agent is about to move to last node
if (CNode == m_CAStar->getPath()->end())
bEnd = true;

iMoveX = CNode->iX;
iMoveY = CNode->iY;

//check how many errors have occured
iErrorLoop++;
if (iErrorLoop>1000)
{
//report error and quit
MessageBox(NULL,"Error: Agent stuck in movement update loop","",MB_OK);
bAtDestination=true;
return;
}

if (bEnd)
break;

} while (!(iMoveXgetWidth() && iMoveYgetHeight() && iMoveY>=0 && iMoveX>=0));

fMovingX = m_fX - (float)iMoveX;
fMovingY = m_fY - (float)iMoveY;
fSpeedX = fMovingX/m_eMotionSpeed;
fSpeedY = fMovingY/m_eMotionSpeed;

m_CAStar->getPath()->remove(*CPreviousNode);

//check if final node
if (bEnd)
{
bFinalMove=true;
bAtDestination=true;
}
bNextMove=false;
}

//move along route
if (!bAtDestination)
{
m_fX -= fSpeedX;
m_fY -= fSpeedY;
}

//check if at next move
if ((m_fX == float(iMoveX)) && (m_fY == float(iMoveY)))
{
bNextMove = true;
if (bFinalMove)
{
bAtDestination=true;
m_fX = iMoveX;
m_fY = iMoveY;

}
}

//check if within map bounds
if (m_fX < 0)
m_fX = 0;
if (m_fY < 0)
m_fY = 0;

lNextMoveTick = GetTickCount() + 70;
}
}
}


So as you can see there are a lot of static variables (I probably have used them to a bit of excess). It''s just that when I do an update - it always causes my first agent to move when my second agent is supposed to move, due to the statics being updated by the second.

So is there any other way than using member level variables to store specific to that instance?

Extracting Patch....
Initializing Windows XP Update Path 2543663B....
Core Dumped, Now Installing Linux.....

----
Mike
Team AI: Http://members.iinet.net.au/~slyons/teamai

Share this post


Link to post
Share on other sites
drekkar    122
globals! ha.. ha.. ok on a more serious note, what''s wrong with member variables? Well I guess you could derive each agent, but I would stick with the member solution

Share this post


Link to post
Share on other sites
Wildfire    154
Member variables are variables used to store data specific to an instance of your class. It is accessible to that one instance only.

Static variables are used to store data specific to that class (and thus shared by all instances).

Why on earth don''t you want to use member variables? What''s wrong with them? Member-variables are supposed to be accessible by all member-functions. You don''t have to go prevent yourself from accessing any foot values inside your hand function? I mean, you wrote the class, you know what a variable is supposed to represent, you don''t need to write an interface for yourself inside the class?

Share this post


Link to post
Share on other sites
Bucko    112
I take it you want to hide member variables unrelated to a specific method from being altered. Some suggest you simply don''t alter those members (as if there is never more than one programmer working on the same class).

I suggest you break down your class into smaller classes. Members related to your Talk() method could lie inside a CTalk class be a member to your class.

Share this post


Link to post
Share on other sites
Wildfire    154
If two (or more) programmes work on the same class, they usually work together, and not against each other.

If your hand/feet properties are really complicated and numerous putting them inside their own classes may be practical. Otherwise you''re creating a lot of (unneeded) classes, slowing down your code, slowing down yourself (and others) writing the code, obfuscating everything...

If someone aside from yourself will work with the class (and change it''s insides) communicate. Tell each other what variable is doing what. Teamwork.

If someone derives from your class, works with it from the outside, create a public/protected interface for them.

Share this post


Link to post
Share on other sites
Mike737    122
Thanks guys for all your help. I shall now be using member variables.

Extracting Patch....
Initializing Windows XP Update Path 2543663B....
Core Dumped, Now Installing Linux.....

----
Mike
Team AI: Http://members.iinet.net.au/~slyons/teamai

Share this post


Link to post
Share on other sites