Structs and Aggregate Initialization
Discover the role of structs, how they differ from classes, and how to initialize them without requiring a constructor.
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.
Creating Structs
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;
}Test your Knowledge
Defining Structs
How could we create a struct that represents a combat ability?
Structs vs Classes (Technical)
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 class and a struct is that, by default, members of a class are private whilst in a struct, they are public.
class Player {
// This is private:
int Level;
// If we want something to be public:
public:
int Health;
}
struct Ability {
// This is public:
int Damage;
// We can still have non-public sections:
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 everything else that a class has.
Everything we have learned (and will learn in the future) about classes also applies to structs.
Structs vs Classes (Semantic)
Even though structs and classes are 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 recommends the following, and many developers/companies have a similar view:
structsshould be used for passive objects that carry data, but lack any functionality other than access/setting the data members.All fields must be
public, and accessed directly rather than through getter/setter methods.Methods should not provide behavior but should only be used to set up the data e.g., constructor,
Initialize(),Reset().If more functionality is required, a
classis more appropriate. If in doubt, make it aclass.
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 Engine, structs have legitimate technical limitations that effectively enforce the "structs are for simple things" convention.
Test your Knowledge
Structs vs Classes
What is the main difference between a struct and a class?
Aggregate Initialization
Aggregate initialization is a feature that simplifies the process of initializing simple objects.
It allows us to initialize the members of a struct or class 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 a 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 the basic idea is that only simple types can be instantiated in this way. If we're adopting the convention of using structs for simple types, aggregate initialization is therefore something we generally use with structs.
If we're creating a more complex type, such as one that has private variables, then aggregate initialization is no longer available. We would need to manually add a constructor, and we'd likely also declare this complex type as a class rather than a struct.
Summary
In this lesson, we explored the concept of structs in C++, exploring their technical and semantic differences from classes. Here are the key takeaways:
- Structs offer a simpler alternative to classes for bundling data together.
- By default, members of a struct are public, unlike in a class where they are private. This is the only technical difference between the two.
- Structs are generally used for passive objects that carry data, without complex behaviors or functionalities.
- Aggregate initialization allows for the simple and direct assignment of values to the members of a struct, enhancing code brevity and clarity.
- The concept of vectors, specifically
Vector3, was introduced as a fundamental type in graphics applications, demonstrating a practical use of structs.
Operator Overloading
This lesson introduces operator overloading, a fundamental concept to create more intuitive and readable code by customizing operators for user-defined types