In this video, we'll learn about static class members and how to use them in c++.
In a c++ class, we can have both static data
and function members.
When we declare class data members as static,
we're telling the c++ compiler that these data members
belong to the class, not to any specific object.
So they're extremely useful to create class-wide information.
For example, suppose we wanted to know how many player objects
we have active in our application at any point in time.
We could create a global variable and then increment it and decrement it in the code
whenever we create an object or delete an object.
This is really hard to do though since we really can't be sure when
constructors are called and when the structures are being called.
So a better solution is to create a static variable that's part of the player class,
and then we can manipulate that variable directly within the player class.
And then whenever we need to know how many player objects there are,
we can simply ask the player class.
We don't even need any objects. In fact, if the player count is 0,
this means that there are no active player objects at all.
So how could we modify our player class to support this.
Let's start with the player class.
We'll create a player.h file with the class specification.
In a player cpp file with the class definition.
Now we need to add a static data member to the class.
We can do this very easily by adding a private static int named num players.
We'll initialize this to 0 a little bit later since we can't initialize it right here.
We also would need to declare a static class function that returns an integer.
It will return the static integer we just declared.
And you can see that at the bottom, it's called get num players.
Now let's head over to player.cpp.
This is where we want to initialize the static integer num players to 0.
Notice that the syntax might look a little strange.
This is where you define that variable and assign it to 0 in this case.
This must happen exactly once and it typically happens
in the .cpp file for the class.
Finally, we implement the static function get num players.
Since this function is static, it only has access to static data members.
It does not have access to non-static class data members.
So in this function, we simply return num players.
Pretty easy.
There's only one part left to do.
We need to increment and decrement the number of players whenever we create and destroy objects.
The best place to increment the player count is in the constructor.
In this case, we simply increment num players by 1.
Be careful though if you have many overloaded constructors
since you might have to increment num players in more than one place.
Basically, anywhere you create an object.
We only have one constructor in the player class and we're delegating to it
from our copy constructor,
so this is the only place we want to increment num players in this example.
Our original player class didn't have a destructor.
It used the compiler provided default destructor since it was all we needed.
However, now we need to define our own destructor and decrement the number of players count
when the object is destroyed.
That's it. We're all set.
Now we can use our player class and simply call player get num players,
and it will return the number of active player objects.
I created a simple helper function named display active players.
And anytime, I need to display the number of active players I simply call it.
Now look at the main. The first statement is display active players, and it will display 0.
As we add and remove player objects, we'll call display active players.
And it will display the current number of active player objects.
Let's head over to the ide, and we'll take the existing player class through the process
of providing this behavior.
Okay. So I'm in the ide, and I'm in the section 13 workspace in the Static
ClassMembers project.
And what I've done is I've created a basic player class,
and you can see here I've got three files:
player.h, player.cpp and main.cpp.
And right now we're looking at player.h.
You can see we've got our our include guard here.
We're included string because we're using strings inside the player class.
And it's a basic player class that we've been using all along. It's got the string
name, the integer health and integer xp.
And we've got a getter here and some
constructor that uses default parameters,
a copy constructor and a d structure that does nothing right now
and the cpp file
implements the constructor, the copy constructor and it's got a
an empty destructor right now.
So what we want to do is we want to go to the player.h file,
and what we want to do as I said in the previous slides is to
know how many players are active at any time. So we need a counter type variable.
We can't add that to objects because then each object would have their own copy.
So we want to use static variable at the class level so that we now have
a variable that applies to the entire class.
So we'll define that right here. We'll make it private, and we'll just say static int,
and we'll call it num players.
Simple as that.
Now you'd you'd think that you could initialize it right here.
But if you try that and try to compile, you'll get a compiler error that says
that c++ forbids in class initialization of non-constant members.
And you can't do that.
So we'll get rid of that, and we'll initialize it in a second in the cpp file.
So that's my
static variable that -- remember,
now this does not belong to any object, this belongs to the class.
And then we need to implement a static
class function. And we'll do that down here.
And we'll just say I call it static. It's going to return an int,
and it's going to be called get num players,
simple as that.
Now one thing to remember, because this function is static,
it only has access to static variables.
That makes sense.
It doesn't have access to any object variables, any of these guys name, health, xp.
Those belong to specific objects.
Static only belongs to the class. So this is a class function,
and it only has access to that static num players in this example.
Okay. We could have a lot of other static functions if we like but we only need the one in this example.
So that takes care of the header file. I'll save that
and now we'll go over to the .cpp file.
Now first thing we want to do is we want to initialize that static variable here.
And the syntax looks something like this int,
the class name
and the name of the variable, num players. And here we can initialize it to 0.
And now you can see that if I compile and run now I get a clean run from that.
So that's initialized. It only happens once.
And the best place to do that is in the cpp file for the class that you're defining.
Okay. And then the last thing we'll do is -- well, not the last thing but do the next thing we'll do is
we'll implement the int player
get num players function.
And it's, let me do that, again get num players,
it's that function right here.
And we're going to implement that function so that it returns
the number of players.
It has access to that. It's a static variable.
And that's really all we care about.
Now remember,we already defined that as a static method right here in player h,
you can see it's right here. So we don't have to say static again down here.
That's it.
Now what do we need to do?Well,
we need to increment and decrement the number of players
depending on when we construct or destruct things.
So this is the only constructor I have.
Even when we've got a copy constructor that we create a copy of an object,
we're still delegating to player.
So right here,
I want to increment the number of players.
And in the destructor, I want to decrement the number of players.
So that will take care of the semantics that I want.
So at that point, this cpp class is done.
And we can now head over to the main class and test some of this.
So the first thing we'll do in the main class is we'll write a real simple function.
And we'll just keep calling that function whenever we want to display active
players. It'll just save us a lot of typing.
So we'll call it void display
active players.
It doesn't expect anything
and all we're going to do in here is we're just going to do an output statement
and we'll say something like active players
colon.
And so now how do I know how many active players there are?
I don't have any objects to call. That's the whole point.
I can simply say player,
and we need a scope resolution operator. And now we can call the static method
get, num players right here.
That's going to return the integer that represents
that static data member that we had in the class.
And we'll just supply an endline here.
Okay. So now let's go to main, and let's call that method.
Let's just call display active players.
All right. We'll put a break point in here
so that we can walk through this. And let's run this,
and we have an error display active players that can't find it players.
I spelled it wrong, let me put an s up here.
And now we should be good to go.
So let's step through it through the debugger,
and I'll move this output window here over to the right again.
And so what do we expect here.
Well, we're going to call display active players and display active players is simply going to ask
the player class to get the number of players. At this point, we have none.
There's no way we could have done this if we had an object, right.
Because there are no objects. So in this case, we're calling player
and asking the player class to give us the number of players.
And we expect this to display 0. When we walk through it,
we get active player 0 just exactly what we expect.
Now let's create an object.
And let's create a player,
and we'll just call it hero.
And we'll give it the name hero, and we'll default everything else.
And then we'll call display active players again.
So at this point, we have one active player. So let's debug this.
We'll step through it again.
And right now, again, we're displaying active players we're. Going to get back to 0.
I'm going to create my player object. It exists. You can see it right here.
So we expect that we've got number of players is one.
And if you look right here in your local variables pane, you can
see that we've got that num players static variable right here.
And we have access to it here. So it's nice because you can actually see it. So at this point,
we run it we get back the one,
which is exactly what we expect since we do have one object.
Okay. So now let's do another example here. Let's create a local block here.
And we'll create another player,
and we'll call that player frank,
and again we'll default it to frank.
And then we'll display active players right in here.
And then we'll display it again when we leave the block. Now what we expect to happen here
is we expect that
this frank object will be created in this local block
will display. Now we'll have two objects, right. We'll display two objects.
Then it's going to go out of scope and be destroyed.
So when we get back to here, it's going to display one less again. So let's do that one more time.
We'll run through the debugger. And we'll step through this one line at a time.
Here we go, display active players. We expect I'll expand this here.We expect it to
display 0, which it does. I just created the hero.
And I want to display the active players, I have one.
Now I'm here. I'm creating frank.
And I'm displaying active players.
I've got two. And obviously, I can refresh over here.
And I can see in both places that I've got two players.
That's that static data member right there.
Now we expect frank to go out of scope, so the destructor will be called,
right. It just got called. So if we refresh now,
we've got hero, and we're back down to one. And we display
back down to one.
Eventually, we'll destroy hero, again, as well.
And we'll get down to 0. Now let's do just one more little piece of code here.
And what we'll do is we'll do it right here at the bottom.
Again, we'll say player.
We'll create an enemy, which is a pointer to a player.
And we'll create a new enemy,
and we'll just call him enemy
and make him pretty strong.
Okay.
And right now what we'll do is we'll display active players
and then we'll delete enemy.
And we'll display the active players one more time.
Okay. So let's walk through this one last time.
And you can see how useful using these static data members is.
So I'm displaying active players,
I get back a 0, I create player, I display that to players again,
I get back a one, which is what I expect. I create frank,
so that gives me two objects. And when I display them, I get the two.
Frank just got destroyed. So I'm going to display one again.
Now here I'm going to create that enemy
object on the heap since it's a dynamic allocation.
And I display active. I've got two again.
I'm going to delete enemy. I'm back down to one.
And at this point, the hero will be deleted, and I'll go back to 0.
Okay. So there you go. There's a real simple example that's using the multiple files here
to declare some static data members, a static
class function and we've got a pretty useful little um
technique that's used a lot.
Sometimes you really need to know how many of your objects are out there, and this is
really easy way to do it.