In some of our class examples, we suggested that our objects should have properties like WorldPosition
- where that character currently exists in the world.
In 3D environments, this is represented as three separate numbers, or coordinates, typically called x
, y
, and z
We could store this as 3 separate variables. But it is usually much better to package these coordinates together, so they can be used and transferred as a single object.
This means we need to create a new custom type of data.
We've already seen how to define a new data type using a class
, but there is an alternative - something called a structure, or struct
:
struct Vector3 {
float x;
float y;
float z;
}
Vector3
?A vector is a term taken from maths - it simply refers to a container for storing a collection of related variables - often numbers.
Vectors are the most common way of representing position and directions within a space we’re simulating. Therefore, a custom Vector3
type (sometimes abbreviated to Vec3
) is typically one of the most fundamental types within graphics applications.
The 3 in the type name indicates it is a 3-dimensional vector, used to store a position in a 3D environment.
We build out our knowledge and application of vectors in several lessons throughout the rest of the course.
How could we create a struct that represents a combat ability?
You may be thinking this problem could also be solved by classes. This is completely true - Vector3
could indeed be a class.
In C++, structs and classes are almost identical. The only difference between a struct and a class is that, by default, members of a struct
are public
whilst in a class
, they are private
.
Aside from that, there is no difference - we create and use structs in the same way we do classes. Structs can have functions, constructors, destructors, and more. and everything else that a class has.
Everything we have learned (and will learn in the future) about classes also applies to structs.
Even though structs and classes are technically almost identical, the C++ community still attaches semantic differences to the two concepts.
The general sentiment is that structs are for creating simpler types, whilst classes are for creating more powerful types.
Google's style guide offers a good example, and many developers/companies have a similar approach:
structs
should be used for passive objects that carry data, but lack any functionality other than access/setting the data members.Initialize()
, Reset()
.class
is more appropriate.class
.Moreover, the difference between classes and structs may become slightly more important when working within the context of other ecosystems, such as a game engine.
For example, in Unreal, structs have legitimate technical limitations that effectively enforce the "structs are for simple things" convention.
What is the main difference between a struct and a class?
Aggregate initialization is a feature that simplifies the process of initializing simple objects.
It allows us to initialize the members of a struct or an array directly without needing to explicitly define a constructor.
Consider our earlier Vector3
struct:
struct Vector3 {
float x;
float y;
float z;
};
In a typical scenario, you would need to define a constructor to initialize these values. However, with aggregate initialization, you can directly assign values to x
, y
, and z
when creating an instance of Vector3
. Here's what it looks like:
struct Vector3 {
float x;
float y;
float z;
};
int main() {
Vector3 Position {1.9, 2.6, 0.3};
}
In this example, Position
is an instance of Vector3
with x
, y
, and z
initialized to 1.9
, 2.6
, and 0.3
respectively.
Aggregate initialization is not always available. We cover it in detail in the advanced course, but for now, we should note that it is more likely to be an option when our types are simple.
As such, if we’re adopting the convention of structs being for simple types, aggregate initialization is much more likely to be available to instantiate structs than classes.
With a type that uses more advanced features - such as private
sections - aggregate initialization is less likely to be an option, and we need to go back to defining an appropriate constructor manually.
In this lesson, we delved into the concept of structs in C++, exploring their technical and semantic differences from classes. Here are the key takeaways:
Vector3
, was introduced as a fundamental type in graphics applications, demonstrating a practical use of structs.Previously, we've seen how built-in objects like int
and bool
allowed us to use operators like +
and >=
to interact with them.
int SomeInt { 2 };
int AnotherInt { SomeInt + 5 };
bool SomeBool { AnotherInt >= 10 };
bool AnotherBool { !MyBoolean };
It would be useful if we had a way to define operators for our custom types too. For example, we'll need the ability to add two of our vectors together.
We could define a function on our class or struct to facilitate that. It could allow us to add vectors together by doing something like this:
MyFirstVector.Add(MySecondVector);
But our code would be more expressive if we could just do this instead:
MyFirstVector + MySecondVector;
In the next lesson, we can see how we can update our classes and structs to make these types of interactions possible.
Discover the role of structs, how they differ from classes, and how to initialize them without requiring a constructor.
Become a software engineer with C++. Starting from the basics, we guide you step by step along the way