



한 줄 답: C++에서 기본 타입만으로 의미 표현이 부족할 때, 관련 데이터를 묶고 잘못된 상태를 방지할 수 있도록 용도에 맞는 사용자 정의 타입(struct, class, enum, variant)을 설계하고 선택합니다.
이 글은 A Tour of C++ 2.6 Advice 학습노트를 기준으로 정리한 내용입니다. 2장(User-Defined Types)에서 배운 struct, class, enum, union, variant를 어떻게 사용하는 것이 좋은지 정리하는 절이며, 2.5 Unions의 union 메모리 구조를 다시 처음부터 설명하지는 않습니다.
struct·class·enum·variant는 언제 고르면 됩니까?
한 줄 답: 연관된 데이터 묶음은 struct, 구현을 숨기고 인터페이스만 노출할 때는 class, 상탯값 집합은 enum class, 여러 타입 중 하나의 값을 타입 안전하게 보관할 때는 std::variant를 선택합니다.
기본 타입인 int, double만으로 의미를 충분히 표현하기 어렵다면 의미가 드러나는 타입을 직접 만듭니다. 학습노트의 예제는 다음과 같습니다.
struct Celsius {
double value;
};
단순한 double temperature보다 Celsius라는 타입이 값의 의미를 더 명확하게 표현합니다. 서로 관련된 값은 각각 따로 관리하기보다 하나의 개념으로 묶는 것이 좋습니다.
struct Point {
double x;
double y;
};
반면 외부에는 필요한 interface만 공개하고 내부 구현은 숨기고 싶다면 class를 사용합니다.
class Counter {
public:
void increment();
private:
int value = 0;
};
struct는 기본 접근 권한이 public인 class라고 볼 수 있습니다. 다음 예제에서 A::x는 public이고 B::x는 private입니다.
struct A {
int x; // public
};
class B {
int x; // private
};
이름이 있는 상수 집합을 다룰 때는 상태를 0, 1, 2 같은 숫자로 직접 표현하기보다 enum class로 의미 있는 이름을 사용합니다.
enum class State {
idle,
running,
error
};
[이미지] struct·class·enum·variant 선택 기준
naked union 대신 std::variant를 선호하는 이유는 무엇입니까?
한 줄 답: 프로그래머가 직접 상태를 관리해야 하는 naked union과 달리, std::variant는 현재 어떤 타입이 활성화되어 있는지 스스로 추적하여 타입 안전성을 보장하기 때문입니다.
union만 직접 사용하면 어떤 멤버가 active member인지 프로그래머가 직접 추적해야 합니다.
union Value {
int i;
double d;
};
필요하다면 tag와 union을 class 안에 함께 넣어 상태를 관리할 수도 있지만, 가능하면 naked union보다 std::variant를 선호합니다.
std::variant value;
std::variant는 현재 어떤 타입이 들어 있는지 스스로 관리하므로 raw union보다 타입 안전하게 사용할 수 있습니다. 또한 상태값을 단순한 숫자처럼 취급하기보다, 해당 enum이나 variant의 의미에 맞는 함수·연산을 함께 정의해 안전하게 사용하는 것이 좋습니다.
[이미지] naked union과 std::variant 비교
2.6 Advice가 말하는 타입 설계의 핵심 철학은 무엇입니까?
한 줄 답: 데이터의 의미를 명확히 표현하는 타입을 정의하고, 생성자(Constructor) 등을 통해 객체가 생성되는 순간부터 유효한 상태를 보장하게 설계하는 것입니다.
class User {
public:
User(int id) : id{id} {}
private:
int id;
};
2장의 핵심 철학은 데이터의 의미를 타입으로 표현하고, 잘못된 상태를 만들기 어렵게 설계하라는 것입니다. 다음 두 코드를 비교하면 그 차이가 드러납니다.
// 나쁜 예
int status = 0;
// 좋은 예
enum class Status { idle, running, error };
Status status = Status::idle;
int status는 어떤 값이 유효한지, 각 숫자가 무엇을 뜻하는지 타입만으로는 알 수 없습니다. 반대로 enum class Status는 가능한 상태를 이름으로 제한하여, 정의되지 않은 값이 들어올 수 없게 만듭니다. 이처럼 struct, class, enum, variant를 목적에 맞게 골라 사용하는 것이 2.6 Advice가 전달하는 핵심입니다.
FAQ
Q. struct와 class의 차이점은 무엇입니까?
A. 기본 접근 권한(Access Level)이 다릅니다. struct는 기본값이 public이며, class는 기본값이 private입니다. 용도에 맞게 선택하여 사용합니다.
Q. 상태를 표현할 때 int 숫자 대신 enum class를 권장하는 이유는 무엇입니까?
A. enum class는 코드의 의미를 명확히 드러내고, 이름 충돌과 의도치 않은 암시적 정수 변환을 방지하여 더 안전한 코드를 작성할 수 있게 해주기 때문입니다.
출처
C++ 학습노트 — 2.6 Advice
Short answer: When built-in types are insufficient in C++, design and choose the appropriate user-defined type (struct, class, enum, variant) to group related data and prevent invalid states.
This post follows the A Tour of C++ 2.6 Advice study notes. It summarizes how to use struct, class, enum, union, and variant, which were introduced earlier in Chapter 2 (User-Defined Types), and it does not re-explain union memory layout from 2.5 Unions from scratch.
When should you choose struct, class, enum, or variant?
Short answer: Use struct to group related data, class when you want to hide implementation and expose only an interface, enum class for a fixed set of named states, and std::variant when you need to hold one of several types in a type-safe way.
If built-in types like int and double can't express meaning clearly enough, define a type that makes the meaning explicit. The study notes give this example:
struct Celsius {
double value;
};
Celsius expresses the meaning of the value far more clearly than a plain double temperature. Related values should be grouped into one concept rather than managed separately.
struct Point {
double x;
double y;
};
When you want to expose only the necessary interface and hide the implementation, use class instead.
class Counter {
public:
void increment();
private:
int value = 0;
};
A struct can be thought of as a class whose default access level is public. In the example below, A::x is public and B::x is private.
struct A {
int x; // public
};
class B {
int x; // private
};
For a set of named constants, use enum class instead of representing state directly as 0, 1, 2.
enum class State {
idle,
running,
error
};
[이미지] choosing between struct, class, enum, and variant
Why prefer std::variant over a naked union?
Short answer: Unlike a naked union, which forces the programmer to track state manually, std::variant tracks which type is currently active on its own, guaranteeing type safety.
Using a union directly means the programmer has to track which member is the active one.
union Value {
int i;
double d;
};
If needed, a tag and a union can be combined inside a class to manage state, but wherever possible, prefer std::variant over a naked union.
std::variant value;
std::variant manages which type is currently held on its own, making it more type-safe than a raw union. It's also better to define operations that match the meaning of an enum or variant, rather than treating a state value as a plain number.
[이미지] naked union vs std::variant
What core design philosophy does 2.6 Advice teach?
Short answer: Define types that clearly express the meaning of your data, and design them — for example through constructors — so that objects are guaranteed to be in a valid state from the moment they are created.
class User {
public:
User(int id) : id{id} {}
private:
int id;
};
The core philosophy of Chapter 2 is to represent the meaning of data through types, and to design those types so invalid states are hard to create. Comparing these two snippets shows the difference:
// bad
int status = 0;
// good
enum class Status { idle, running, error };
Status status = Status::idle;
With int status, the type alone tells you nothing about which values are valid or what each number means. enum class Status, on the other hand, restricts the value to a named set of possible states, so an undefined value can't be assigned in the first place. Choosing struct, class, enum, or variant to fit the purpose is the core message of 2.6 Advice.
FAQ
Q. What's the difference between struct and class?
A. The default access level differs. struct defaults to public, while class defaults to private. Choose whichever fits the purpose.
Q. Why is enum class recommended over using a plain int to represent state?
A. enum class makes the code's intent explicit and prevents name collisions and unintended implicit conversions to integers, leading to safer code.
Sources
C++ study notes — 2.6 Advice
'C++' 카테고리의 다른 글
| std::map vs std::unordered_map 차이: 언제 무엇을 쓰나? (0) | 2026.10.10 |
|---|---|
| C++ union은 왜 위험한가? active member부터 std::variant까지 (0) | 2026.09.29 |
| C++20 jthread stop_token 사용법, 스레드 취소를 어떻게 하나 (0) | 2026.09.22 |
| C++ class, 생성자로 불변식을 잡는 법 (0) | 2026.09.19 |
| C++ 1.7 포인터와 레퍼런스 정리: 주소, 배열, 참조, nullptr까지 (0) | 2026.09.19 |
