Sign in to follow this  
_Sigma

Static var question

Recommended Posts

I've been reading the Enginuity articles (amazing btw :D) and I have a quick, really dumb question. I've never dealt with static variables in a class before, so if you have a class like thus:
class IMMObject
{
   private:
      static std::list<IMMObject *> liveObjects;
      statid std::list<IMMObject *> deadObjects;
      long refCount;
   protected:
      IMMObject();
      ~IMMObject();
   public:
      void AddRef();
      void Release();
      static void CollectGarbage();
};

std::list<IMMObject *> IMMObject::deadObjects;

void IMMObject::Release()
{
   --refCount;
   if(refCount<=0)
   {
      liveObjects.remove(this);
      deadObjects.push_back(this);
   }
}

void IMMObject::CollectGarbage()
{
   for(std::list<IMMObject *>::iterator it=deadObjects.begin();
       it!=deadObjects.end(); it++)
   {
      delete (*it);
   }
   deadObjects.clear();
}

IMMObject::IMMObject()
{
   liveObjects.push_back(this);

   //update the constructor to initialise refCount to zero
   refCount=0;
}

Any class that inherites or uses IMMObject will get the same copy of liveObjects and deadObjects right? So:
IMMObject obj1;
liveObjects will contain obj1. now lets say I go:
IMMObject obj2;
then liveObjects will contain obj1 and obj2, right? Also, why is a method static? whats the point in this? Cheers

Share this post


Link to post
Share on other sites
correct ...

and the point of a static method is to be able to call a function (which probably manipulates static data) without having created an instance ...

For instance you could call something like

int count = IMMObject::LiveObjectCount();

to reach the size of the list without having to create an IMMObject just to get the count :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Xai
correct ...

and the point of a static method is to be able to call a function (which probably manipulates static data) without having created an instance ...

For instance you could call something like

int count = IMMObject::LiveObjectCount();

to reach the size of the list without having to create an IMMObject just to get the count :)


Additionally, static member functions follow class permissions (public, protected, private). So you cannot access liveObjects or deadObjects, but CollectGarbage() can.


jfl.

Share this post


Link to post
Share on other sites
Quote:
Original post by Xaiand the point of a static method is to be able to call a function (which probably manipulates static data) without having created an instance ...


Also, do note that by that token, you cannot directly access non-static member variables/functions from a static member function.


jfl.

Share this post


Link to post
Share on other sites
Yes.

Now what you can do is the following:

class test {
private:
int a;
static int b;

public:
test( int a ) : a( a ) {}

static int returnAB( const test &instance ) {
return instance.a * b;
}
};
int test::b = 20;


int main() {
test t( 2 );
test::returnAB( t ); // returns 40
}

[edit] Now, alone, this may not seem particularly useful -- since you are in fact imitating a non-static member function -- but it can be useful in cases like this, where you would like to use a non-static method as a callback (for instance).


jfl.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Conner McCloud
Quote:
Original post by _Sigma
and why is it test::returnAB( t ); // returns 40
Can it be test.returnAB( t ); // returns 40,? cheers!

No. test is a namespace, and as such uses the namespace resolution operator.

CM


Though you can use t.returnAB( t ); because t is an instance of the class test.

Share this post


Link to post
Share on other sites
Right. You can use both because returnAB is a member of the class nonetheless, though it can resemble a namespace. [edit2] It should be t.returnAB, not test.returnAB.

Also, instance is a constant reference to test object ( const test &instance ). You could implement returnAB similarly using a pointer:
static int returnAB( const test *instance ) {
return instance->a * b;
}

You would then use it like this:
test t( 2 );
test::returnAB( &t );

I chose to use a reference because you cannot have an invalid reference (unless you do something really weird), and because I do not need the concept of "no reference" in that example.


[edit] It is not a namespace. Conner McCloud must have skimmed over the code rather rapidly ;). [edit3] I think I see what you mean, CM. Disregard.



jfl.

[Edited by - jflanglois on November 4, 2005 10:48:34 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Conner McCloud
Quote:
Original post by _Sigma
how did that become a namespace? :S

All classes have a namespace [of the same name] associated with them.

CM


Oh. Is it literally a namespace? How come I cannot use a namespace with the same name afterwards, then? [edit] Upon re-reading, I assume you mean that test.returnAB should be t.returnAB because test is effectively a namespace while he would need an instance to use that form?

Share this post


Link to post
Share on other sites
Ok, ya, I meant t.blah not test.blah

I'm a tad confused, and my code isn't compiling, as this is my first time using MS VC instead of Borland. I'll read this tomorrow when I'm awake :P

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this