Structures, enumerations, and type aliases
Create meaningful user-defined data types with struct, enum class, and using.
Learning objectives
- Group related values in a
struct. - Access members with the dot operator.
- Use scoped enumerations to represent a fixed set of choices.
- Create a readable type alias with
using.
Prerequisites: understand variables, basic types, functions, and arrays. Review Variables and Functions if these are unfamiliar.
Why create your own type?
Suppose a program stores a student's name, roll number, and marks. Three unrelated variables work for one student, but become confusing for many. A structure groups related data into one type.
#include <iostream>
#include <string>
struct Student {
std::string name;
int roll_number{};
double marks{};
};
int main() {
Student learner{"Asha", 17, 88.5};
std::cout << learner.name << ": " << learner.marks << '\n';
}The structure definition declares a new type named Student. The object learner contains its own name, roll_number, and marks members. Use the dot operator (.) to access a member of an object.
Aggregate initialization
This example initializes members in their declaration order. For a simple aggregate, brace initialization is a clear way to provide each member's starting value. Member order matters: the first initializer corresponds to name, the second to roll_number, and the third to marks.
Scoped enumerations
An enum class defines a distinct type whose values are named choices. It avoids many accidental conversions and name collisions associated with older unscoped enums.
enum class Status { pending, approved, rejected };
Status application{Status::pending};
if (application == Status::pending) {
// review the application
}Write the enum name and :: before the enumerator. This makes the meaning explicit.
Type aliases with using
using StudentId = unsigned int;
StudentId id{42};A type alias gives an existing type another name. It does not create a completely new distinct type; it creates a readable alternative name for the same type.
Common mistakes
- Mixing up member order in aggregate initialization.
- Using
.on a pointer instead of->(covered with pointers). - Comparing unrelated enum values or expecting implicit integer conversion from
enum class. - Thinking
using Name = Type;creates a strongly distinct type.
Practice
- Define a
Bookstructure with title, author, and page count. - Create an enum class for order status with placed, shipped, and delivered.
- Write a function that accepts a
const Student&and prints its name.
Practice solutions
Show worked solutions
#include <string> struct Book { std::string title; std::string author; int page_count{}; };Aggregate initialization can then be used to provide the three member values.enum class OrderStatus { placed, shipped, delivered };Scoped enumerators are named throughOrderStatus::.#include <iostream> #include <string> struct Student { std::string name; }; void print_name(const Student& student) { std::cout << student.name << '\n'; }The const reference avoids copying the object and prevents this function from modifying it through that parameter.
Check your understanding
What is the main purpose of a struct?
Answer: To define a type that groups related data members under one name.
Summary
Use structures to model related data, scoped enumerations for a fixed set of named states, and aliases to improve readability. These features help your program express its data model clearly.