In this video, we'll learn the basic syntax for declaring a class in c++.
The syntax is very simple.
First we use the reserve keyword class followed by the name of the class we're declaring.
Notice that it's best practice to capitalize class names for our user-defined classes.
Then we have a block which are open and close curly braces,
and the class declaration is terminated with a semicolon.
In the body of the class declaration,
we can supply the declarations that define the structure and behavior of our class.
Let's see an example.
Here we're declaring a class name to player as we might have in a game application.
Notice the class keyword followed by the name of the class, in this case, player.
Then in the body of the class,
we can define the classes attributes or instance variables and methods.
In this case, the class has a string named name
and two integers representing the player's health and xp.
Since c++ supports encapsulation,
that means we can also provide methods or functions in the class body
that are specific to the player class.
In this case, we have two methods talk which expects a standard string
and is dead which returns a Boolean.
Now that we've created the class,
we can create objects that are instances of that class.
So in this example, I'm creating Frank and hero which are player objects.
Notice the syntax, it should feel familiar since it's the same way we create primitive types.
We can also create pointers to objects.
In the last example, I'm declaring enemy as a pointer to a player object,
and I'm creating that object dynamically on the heap using new.
When I'm finished using enemy object, its storage has to be freed up using delete.
Here's another example where we declare an account class.
Notice that accounts have a name, which is a standard string
and a balance, which is a double.
And in this example, we have a withdraw method that expects the amount to withdraw
and returns a Boolean indicating success.
We also have a deposit method that expects the amount to deposit
and also returns a Boolean indicating success.
We'll talk more about how we define class methods in a few videos,
but notice how they're basically function prototypes in these examples.
Now that we've declared the account class, we can create objects of that type.
So Frank's account and Jim's account are objects or instances
of the account class.
In the last declaration, Mary's account is a pointer to an account object
that again has been allocated dynamically on the heap and then freed up when we're done with it.
Once we have objects, we can use them like any other variable in c++.
For example, we can create an array of account objects
and initialize the array to Frank's account and Jim's account.
We can create a standard vector of account objects and initialize it to Frank's account
and then push back Jim's account.
You can see how easy and how readable our code looks.
We're using our own user-defined types, and we're using them intuitively
like we've used other c++ types.
In the next video, we'll see the syntax for accessing the attributes
and methods and objects.
But first, let's head over to the IDE and create these classes.
Okay. So I'm in the IDE. I'm in the section 13 workspace,
the DeclareClassAndObjects project.
This is just an empty little project right now with an empty main.
I've included iostream, string and vector.
And I'm using namespace standard.
Remember, you really don't want to use namespace standard all the time.
You really want to be explicit and type out
scope resolution operator and whatever you need,
but I'm going to do it because it'll save me a lot of typing
time, otherwise these videos could be a pretty long with me making typos.
So what do I want to do here? Let's create the player class, the account class,
and we'll create some objects.
The first question is where do we create the player class.
Let's do the player class first.
I could do it right inside main. I could say class player
and define that class right in here.
That's really not what i want to do. Because if I do that, then I'm defining that
class inside the scope of main,
which means that only main will have access to that class,
and that's not really what I want.
I want to create my player class so that the entire application has access to it.
So I'm going to do it right up here.
And then later on in this section, we'll learn how to do it an even better way.
We'll use separate files to do it. But for now, let's learn about classes and objects.
So what I want to do is I want to say class player.
Remember, the class name should be an upper case.
And you need a semicolon right here at the end of the class declaration.
So what do we put inside this class declaration.
Well, we saw in the slides that you can put attributes in here, that's typically data.
And we can put methods in here, which are operations or functions.
That's what encapsulation is all about, putting all these things together.
Now what do you put in here?
Well, it depends. It depends on what a player is in the context of your application.
It could have all kinds of stuff in here or could have a minimal amount of stuff in here.
That's the whole point. You really don't want to model a player
that could be used in any application in the world.
You just want to model a player that's going to be used in your application
that you can extend easily.
Okay. So don't try to model like the the best player object
or class you could ever have, just solve your problem.
So in this case, let's assume that a player has or a name which is a string.
And the player has an integer
which is their health and let's say something like between 0 and 100.
0 health, you're dead, and xp which is experience
and that could be 3 up to whatever, it doesn't really matter.
It's all based on our application.
So now what we're saying here is that the class player is going to be a blueprint
to create player objects from
and every player object is going to have a string that represents their name,
two integers; one representing their health, one representing their xp.
Okay. Now what methods can we have? We can have a ton of methods.
Let's just create two of them really simply so you understand how this works.
What you do here is you basically do everything we learned when we talked about functions.
So I want to have a method called talk,
and it expects a string. So whatever string you pass into the player,
the player will talk it right back out.
And let's say we want to have is dead.
This is a method that returns true or false
based on whether the player is dead.
And the player might be dead if their health is 0 or whatever other criteria we have for that.
Okay. Again, notice that what these look like are basically function prototypes at this point.
We could implement them right here and we will in a couple of more videos.
But for now let's just think these are the attributes, these are the methods.
Okay.
Also there's the concept of public and private.
What we have access to we'll get to all that really, really soon.
But that's it. That's a minimal player class given this,
I can create player objects.
Now let's create two player objects right here in main.
I'll say player Frank
and player Hero.
That's it.
When these two lines execute, the system will create two player objects.
One is called Frank, one is called Hero.
Each one of them has a name, health and xp.
Each one of them can call these methods and talk and
ask if it's dead or not.
Okay. So hopefully that makes sense.
Let's run this right now. We're going to run this in the debugger so you can see them.
What I'm going to do is I'm going to first I'm going to save this then I'm going to click right here in the gutter,
and you get that little stop sign for the debugger.
And then what I'm going to do is just go to debugger start debugger or you can just press F5.
And I've got my debugger set up so that my local variables are over here
any watches that I want to look for here and then here.
The call stack is real simple, we're just in main right now.
You can see I've got my two local variables.
You can see them displayed right up here. I've got Frank and I've got Hero.
Right now, they don't really exist because I haven't created them yet,
but they're in the local variables pane here.
So what I want to do is let's create Frank in here.
I'll just hit the next arrow down here,
and Frank is now active and then Hero is now active.
And if you expand these guys a little bit,
you can see something of what's going on here
you can see Frank has a name, right, of course, here it is. It's one of the attributes.
Frank has health, and Frank has xp notice it's garbage data right.
The only reason that the string is not garbage is because
our c++ string class, our standard string class
has a default initializer which initializes it to empty, which is pretty cool.
But the rest of this stuff is junk, just garbage data.
The same thing with health and the same thing with xp.
This is the same sort of behavior we saw when we created regular variables.
Okay so we'll talk about initializing these objects
in a couple of videos where we use constructors to do it
and that makes things much much easier.
Okay. So I'm going to stop this debugger.
And we can also create objects on the heap,
on the heap,
just like we could regular primitive types. So in this case, I'm going to say
player
enemy is a pointer to a player. Remember, you read these from right to left.
And you know what let's set it to null pointer. I'm going to do this in two steps just, so you can see
this happening in the debugger. Then I'm going to say enemy
equals new player.
That's going to create the enemy on the heap,
that enemy object, which is a player.
And then I'm just going to say delete enemy when I'm done.
Okay. So let me move that right to about there.
And let's run this again in the debugger.
Here you can see that right now there's garbage data
in the value for enemy, right. So it exists.
It's a pointer. It's got a value, and it's junk right now.
So when I execute the statement, I just nulled it out.Now you can see it's 0.
That's the safe way to do things.
Now I want to create this new player object on the heap.
So right now when I execute that statement, you expect that address to change,
right. Because obviously I'm creating this on the heap,
and I'm storing the address of that object in enemy, which is a pointer.
So let's step through it. Here we go.
At this point, that enemy object is created.
It's on the heap. It's a player, right, that's its type.
And if I expand this, you can see that the name is empty but health and xp contain garbage,
just what we would expect. And then when we're done with it, we can delete it.
Okay. Really, really straightforward.
Let me add a few lines of code right in here,
and we'll get rid of that break point and we'll move it in a second.
Once we have these objects, we can treat them like any variables,
just like we've worked with integers and doubles and everything else.
So in this case, suppose I want to create an array right here
called players,
and it's an array. And I want to set it to Frank and hero,
right just like we've done with integers. It's the same idea.
So let's read this together here. It says players is an array
of player objects.
Well, I've got two of them right here. So I can initialize that array to Frank and Hero.
I'm going to save this,
and let's put a break point right there so we can look at it and we'll run it.
Okay. So you can see players is right here and I'm going to step through it.
So now player has been initialized here to those two objects:
the first object and the second object.
The first object is Frank, the second object is hero.
And you can tell we don't have any strings for names now but you can tell from the garbage
values that they really are indeed those objects.
So it's really as simple as that.
This is very powerful stuff because we can create our own
user-defined types, which is what player is.
And then use it just like we can use any other variable.
Okay. So last thing is let's try
to create rather than an array here.
Let's do a vector. So let's create a vector. A vector of what.
Well, we've done vectors of integers and vectors of strings.
Well, why not a vector of player.
Okay. And we'll just call it player vec.
So again, what is this? This is a collection of player objects.
Okay. So let's initialize this to Frank. That's a player object.
And then what we could do is we can ask the player vec
to push back, remember, push back as a method in the vector class.
And we can push back hero,
right. So let's execute both these lines, and again I'll put a
break point right there,
and we'll go back to the debugger and run this.
So right now we have player vec, so I'm going to step into it here so that I can create that vector.
Okay. The vector is now created. It's called player vec, it's right here.
If I expand it, you can see that right now there's one item in there,
and that one item is Frank. If you look at frank up here,
you could see it's garbage data right here.
Well, it's going to be the same garbage data right here because we just copied that object.
Okay. Now when I execute the next line,
which I'm going to just by clicking next here
that should add hero to that vector. So let's do that.
And now you can see -- you notice here that it didn't really show up here,
this player vec.
What you can do when that happens is you need to refresh right here.
So when i refresh see right now it says there's only one item in there, we know there are two.
So if you refresh and then expand player vec,
there you go. Now you see both items. In this case, that's Frank. And in this case,
that's hero.
Okay. So all this works exactly like it did with integers and doubles and so forth.
All right. So let's create an account class now real
quick, and we'll do it right below the player class. We'll create a class account.
We'll create the body, and we'll put a semicolon on the end.
Don't forget that semicolon. If you forget that semicolon, you're going to get compiler errors.
And they're going to be strange compiler errors
because the compiler is going to be lost trying to figure out where you are.
Okay. So here we can have attributes.
And what we'll say here is again we've got a string name, a name of an account
and we've got a double, which is called balance.
And then here we can have methods, again, as many methods as we want.
Now you'll notice that over here,
I just prototyped those two methods. I just declared them, I never defined them.
So how in the world did this work. Well, this worked because I never called them.
If I had called those methods,
I'd have a linker error because the linker is going to say I don't know where those things are.
You told me they were there, but I don't know where they are. Okay.
We'll implement all this stuff in the next few videos.
So let's create a couple of methods. Bool
deposit and a double
and bool withdraw double.
Those are my two method declarations.
I want to deposit some amount, and I'm going to return true false whether it was successful or not.
and I'm going to return true false whether it was successful or not.
I want to withdraw some amount again it's a double,
and I want to return true or false, depending on whether it was successful.
Once that I've got -- once I've got that class declared,
I can now create account objects.So I could say Frank account,
I could say Jim account and so forth.
Okay. And then I'll put a break right here.
And let's check that out in the debugger.
You can see right here is Frank account.So I'm going
to go next and next again,
that's created those two objects. So here Frank account
has a name. It's empty, and it's got a garbage number for balance.
And the same thing for Jim account. It's got a name, and it's got a balance.
Okay. Now something that's useful in c++11 and going
forward is that you can actually initialize these guys right here.
So let's just say that I wanted to initialize that to Frank -- to account, sorry.
And I wanted to initialize balance to 0.
I can do that,
and I can also do this up here. So let's just say I wanted to initialize this to player.
If you think about this, it's really odd that they're letting you do this at all because we're
creating these initialization variables here,
but we don't even have objects yet right. I mean this is just a class declaration.
We don't have any objects, but they can come in handy.
And I'll show you how to initialize these things using
constructors and initializer lists in a little while. But let's say that
that xp is three and the health is a 100.
Okay. So let's run this again this time.
And I'll stop the debugger and start it again.
Oops, forgot my semicolon
and probably forgot some down here as well.
So let's run that.
Okay. So now you can see --
let me scroll up a little bit. I'm right here on line 33.
So I'm going to go next, next. I've just created those two accounts.
And again, I'm going to go next, next. And I just created those two players, Frank and Hero.
But now when I look at Frank,
you can see Frank's name is player, it's health is a 100 and it's xp is 3.
So basically any object is going to get these values right here.
And as I said, we'll learn other ways to initialize, but this is pretty nice
right now because we can actually see them in the debugger, and you can see this working.
Okay. And the same thing with the account. Frank account here says account with a balance of 0.
And Jim's account is a count with a balance of 0 as well.
Okay. All right. Perfect. Now in the next video,
what we'll learn to do is we'll learn how to actually access those
class attributes and class methods using an object.
Okay. So I'll see in a little bit.