C++ struct vs class | Access Control·POD·C Compatibility Complete Comparison
이 글의 핵심
C++ struct vs class difference is only default public/private, functionality is identical. Data grouping vs encapsulation convention, POD·C compatibility. Same syntax, compares intent expression and selection criteria.
Introduction
In C++, struct and class differ only in default access control, functionality is completely identical.
To use an analogy, the syntactic difference is like whether to put a ‘public’ sticker on the meeting room door or ‘private’ is default, and what you can do inside the room (methods, inheritance, etc.) is the same. By convention, struct is often used for data grouping, class for objects maintaining invariants.
After Reading This
- Understand the only difference between struct and class
- Grasp usage rules and selection criteria
- Check POD type and C compatibility
- Learn selection strategy by practical scenario
Reality in Production
When learning development, everything is clean and theoretical. But production is different. You wrestle with legacy code, chase tight deadlines, and face unexpected bugs. The content covered in this guide was initially learned as theory, but I realized “ah, that’s why it’s designed this way” while applying it to actual projects. What stands out in my memory is the trial and error from my first project. I did it as I learned from books but spent days not knowing why it didn’t work. Eventually, I found the problem through a senior developer’s code review and learned a lot in the process. This guide covers not only theory but also pitfalls you may encounter in practice and their solutions.
Table of Contents
- struct vs class Difference
- Practical Implementation
- Advanced Usage
- Performance Comparison
- Practical Cases
- Troubleshooting
- Conclusion
struct vs class Difference
Only Difference: Default Access Control
| Item | struct | class |
|---|---|---|
| Default access control | public | private |
| Default inheritance | public | private |
| Constructor | ✅ | ✅ |
| Destructor | ✅ | ✅ |
| Member functions | ✅ | ✅ |
| Virtual functions | ✅ | ✅ |
| Inheritance | ✅ | ✅ |
| Templates | ✅ | ✅ |
Practical Implementation
1) Basic Access Control
Here is detailed implementation code using C++. Import the necessary modules and define a class to encapsulate data and functionality. Understand the role of each part while examining the code.
#include <iostream>
// struct: default public
struct Point {
int x, y; // public (default)
};
// class: default private
class Point2 {
int x, y; // private (default)
public:
Point2(int x, int y) : x(x), y(y) {}
int getX() const { return x; }
int getY() const { return y; }
};
int main() {
Point p;
p.x = 10; // ✅ OK
p.y = 20;
Point2 p2(10, 20);
// p2.x = 10; // ❌ Compile error: private member
std::cout << p2.getX() << std::endl;
return 0;
}
2) Inheritance Default Access Control
Here is detailed implementation code using C++. Import the necessary modules and define a class to encapsulate data and functionality. Understand the role of each part while examining the code.
#include <iostream>
class Base {
public:
void foo() {
std::cout << "Base::foo" << std::endl;
}
};
// struct: default public inheritance
struct DerivedStruct : Base { // public inheritance
};
// class: default private inheritance
class DerivedClass : Base { // private inheritance
};
int main() {
DerivedStruct ds;
ds.foo(); // ✅ OK (public inheritance)
DerivedClass dc;
// dc.foo(); // ❌ Compile error (private inheritance)
return 0;
}
3) struct Can Be Used Like class
Here is detailed implementation code using C++. Import the necessary modules and define a class to encapsulate data and functionality. Understand the role of each part while examining the code.
#include <iostream>
struct MyStruct {
private: // Can specify private
int x_;
public:
MyStruct(int x) : x_(x) {
std::cout << "Constructor: " << x_ << std::endl;
}
virtual void foo() { // Virtual function
std::cout << "MyStruct::foo: " << x_ << std::endl;
}
virtual ~MyStruct() {
std::cout << "Destructor: " << x_ << std::endl;
}
};
struct Derived : MyStruct {
Derived(int x) : MyStruct(x) {}
void foo() override {
std::cout << "Derived::foo" << std::endl;
}
};
int main() {
MyStruct* p = new Derived(42);
p->foo(); // Derived::foo
delete p;
return 0;
}
4) Usage Rules (Google C++ Style Guide)
struct: Passive Object Containing Only Data
Below is an implementation example using C++. Define a class to encapsulate data and functionality. Understand the role of each part while examining the code.
// ✅ Use struct
struct Point {
int x, y;
};
struct Color {
uint8_t r, g, b, a;
};
struct Config {
std::string host;
int port;
bool useSSL;
};
class: Active Object with Encapsulation and Methods
Here is detailed implementation code using C++. Define a class to encapsulate data and functionality, and perform branching with conditionals. Understand the role of each part while examining the code.
// ✅ Use class
class BankAccount {
private:
double balance_;
public:
BankAccount(double initial) : balance_(initial) {}
void deposit(double amount) {
if (amount > 0) {
balance_ += amount;
}
}
void withdraw(double amount) {
if (amount > 0 && balance_ >= amount) {
balance_ -= amount;
}
}
double getBalance() const {
return balance_;
}
};
Advanced Usage
1) POD Type
POD (Plain Old Data) is a simple type compatible with C. POD Conditions (C++11):
- Trivial constructor
- Trivial destructor
- Trivial copy/move operators
- Standard layout (no private/protected members, no virtual functions) Here is detailed implementation code using C++. Import the necessary modules and define a class to encapsulate data and functionality. Understand the role of each part while examining the code.
#include <iostream>
#include <type_traits>
// ✅ POD
struct Point {
int x, y;
};
static_assert(std::is_pod_v<Point>); // true
// ❌ Non-POD (has constructor)
struct Point2 {
int x, y;
Point2(int x, int y) : x(x), y(y) {}
};
static_assert(!std::is_pod_v<Point2>); // false
int main() {
std::cout << "Point is POD: " << std::is_pod_v<Point> << std::endl;
std::cout << "Point2 is POD: " << std::is_pod_v<Point2> << std::endl;
return 0;
}
Summary
Key Points
- struct vs class: Only default access control differs
- struct: For data grouping (default public)
- class: For encapsulation (default private)
- POD: Simple type compatible with C
- Convention: struct for data, class for objects
Decision Flowchart
Need encapsulation?
├─ Yes → class
└─ No (only data)
└─ Need C compatibility?
├─ Yes → struct (POD)
└─ No → struct (convention)
Best Practices
- ✅ Use struct for data-only types
- ✅ Use class for objects with behavior
- ✅ Check POD for C compatibility
- ❌ Don’t mix conventions
- ❌ Don’t use struct for complex objects
Related Articles
- C++ Aggregate Initialization
- C++ Memory Layout
- C++ Object-Oriented Programming Master struct vs class selection! 🚀