Lets create our first C++ class!
The basic structure of a class is this:
class Monster {
public:
// Class code here
};
We use the class
keyword, we give our class a name, eg Monster
, and we open a set of braces - {
and }
to contain our class code.
Within the braces, we add the public:
keyword, and then put our class code below it.
The meaning of public:
will be discussed in more detail in the next lesson.
For now, lets just ensure we include it. Our class code should be between the public:
and the closing brace }
.
The "members" of a class are the variables and functions within that class. They are created in the same way we have seen in the past, as demonstrated in the below example:
class Monster {
public:
// a variable
int Health { 150 };
// a function
void TakeDamage(int Damage) {
Health -= Damage;
}
};
When it comes to object oriented programming, there are lots of different terms for very similar ideas. What we're calling variables and functions here, others might use different names. Names like field, property, and attribute are commonly used.
Similarly, a function that is associated with a class will sometimes be called a method.
At a high level, we can just treat them as different ways to describe the same ideas.
For the remaining of the code samples in this lesson, assume this class is defined as above.
How can we define a class called Car
in C++?
Now that we have our class created, we are able to use it to create Monster
objects. A class is, in essence, the blueprint for how to create objects of a certain type.
The phrases "instance" and "instantiation" are often used to describe these ideas. Each object is an instance of its class. Creating an object from a class is sometimes referred to as instantiating the class.
In one of the first lesson of the course, we saw how we could create an integer:
int MyInt;
In the above example, int
is the type of data. It lets the compiler know what class to use for our new variable.
MyInt
is the name of the variable.it is how we will identify this specific object in our code.
The syntax is exactly the same for our custom data types. The below code gives examples on how we can create a new Monster
object, called Harry
:
Monster Harry;
After running this code, we have a new variable, that has a type of Monster
and a name of Harry
.
What statement allows us to create a new Car object from this class?
class Car {
public:
int Speed { 50 };
}
Once we have an object of the Monster
type, the member access operator gives us access to the underlying variables and functions that the object has, by virtue of it being a Monster
.
The member access operator is the period character .
Monster Harry;
Harry.Health; // 150
Harry.TakeDamage(50);
Harry.Health; // 100
Once we gain access to those variables and functions using the .
operator, we can treat them exactly like we would with any other variable of that type.
A variable that is part of an object can be used and manipulated like any other variable we've seen. For example, if we had an integer variable on a class:
=
, ++
, and *=
.+
and /
.<=
and ==
Monster Harry;
Harry.Health = 100;
Harry.Health += 100;
int HarryHealth { Harry.Health };
bool HarryIsHealthy { Harry.Health > 50 };
int Add(int x, int y) {
return x + y;
}
Add(Harry.Health, 100);
Imagine we had the following code:
class Car {
public:
int Speed { 50 };
}
Car MyCar;
What statement allows us to access the Speed
integer of our object?
::
The above example defined our class function at the same time we define our class. There is another way of doing this. We can define the prototype of the function within the class, and provide the implementation separately, elsewhere.
class Monster {
public:
int Health { 150 };
// the prototype
void TakeDamage(int Damage);
};
// the implementation
void Monster::TakeDamage(int Damage) {
Health -= Damage;
}
Note the addition of Monster::
before the function name in the above example. When implementing functions for a class from outside the {
and }
associated with that class, the ClassName::
is necessary.
The addition of Monster::
tells the C++ compiler that we are providing the implementation of a function that was declared in the Monster
class.
For now, we'll continue to use the first method where we define the whole function as part of the class. I've included the second example as it's actually more commonly used, so it will crop up a lot when looking at other people's code.
The benefit of the second method is that it allows the implementations of class functions to be provided in a completely different place to the class itself - even in a different file.
This is useful for bigger projects, and a pattern we will be a adopting ourselves soon. But for now, we should just keep it simple.
Become a software engineer with C++. Starting from the basics, we guide you step by step along the way