C++ - struct vs class vs union
In C++, struct, class, and union are user-defined types with distinct memory layouts, encapsulation rules, and idiomatic use cases.
struct vs class
Technically, in C++, a struct and a class are almost identical in capability—both support member functions, constructors, destructors, virtual methods, and templates.
The only two syntactic differences are defaults:
- Default Member Access:
struct: members and methods default topublic.class: members and methods default toprivate.
- Default Inheritance Access:
struct Derived : Baseinheritspublicby default.class Derived : Baseinheritsprivateby default.
struct Point {
int x; // public by default
int y; // public by default
};
class BankAccount {
double balance; // private by default
public:
void deposit(double amount) { balance += amount; }
};
Idiomatic Convention (Google C++ Style Guide)
- Use
structfor passive objects that carry data (Data Transfer Objects / Plain Old Data) with public members and no complex invariants. - Use
classfor objects with internal state, encapsulation, invariants, and private data controlled via public member functions.
union
A union is a special class type where all non-static data members share the same memory location. Its size is equal to the size of its largest member (plus any necessary alignment padding).
union DataValue {
int int_val;
float float_val;
char char_val;
};
DataValue val;
val.int_val = 42;
val.float_val = 3.14f; // Overwrites int_val in memory
Key Union Characteristics:
- Single Active Member: Only one member can be safely read at a time (the one most recently written). Reading an inactive member is undefined behavior (type-punning rules).
- No Inheritance / Virtual Functions: A
unioncannot inherit or be inherited from, and cannot declarevirtualmethods. - Modern Alternative (
std::variant): In C++17, usestd::variant<int, float, std::string>instead of raw unions for type-safe, tagged union behavior with exception-safe construction/destruction of non-trivial types.
Comparison Summary
| Feature | struct |
class |
union |
|---|---|---|---|
| Default Member Access | public |
private |
public |
| Default Inheritance | public |
private |
Inheritance not permitted |
| Memory Layout | Sequential (each member has own offset) | Sequential (each member has own offset) | Overlapping (shared base address) |
| Size | Sum of members + padding | Sum of members + padding | Size of largest member (+ alignment) |
| Active Members | All members active concurrently | All members active concurrently | Exactly one active member |
| Idiomatic Purpose | Passive data holder (POD / DTO) | Encapsulated business logic & invariants | Low-level memory optimization / bit-level mapping |
| Modern Alternative | — | — | std::variant (C++17) |