C++에는 여러 데이터 집합을 담을 수 있는 방법이 여러 가지 있는데, 대표적으로 구조체(Struct)와 클래스가 있다.

C++에서 struct와 class는 생각보다 많은 부분이 비슷하지만, 몇 가지 다른 부분이 존재한다.
C++ 표준에서 struct와 class는 문법적으로 거의 동일한 사용자 정의 타입이다.
대표적인 공통점은 다음과 같다.
struct와 class 둘 다 전부 사용 가능struct/class를 상속할 수 있고, 다중 상속도 가능public, protected, private을 자유롭게 사용할 수 있음가장 큰 문법적 차이는 아무것도 안 썼을 때 기본 접근 수준이 무엇인가이다.
class A
{
int x; // 기본: private
public:
void Func();
}
privateprivate으로 취급함struct B
{
int x; // 기본: public
void func(); // 기본: public
};
publicclass PlayerClass
{
int hp; // private
public:
void SetHP(int value) { hp = value; }
};
struct PlayerStruct {
int hp; // public
};
int main()
{
PlayerClass pc;
// pc.hp = 100; // 컴파일 에러 (private)
pc.SetHP(100); // public 함수로만 접근
PlayerStruct ps;
ps.hp = 100; // 바로 접근 (public)
}
class를 사용struct로 사용class Base
{
public:
void Foo() {}
};
class Derived : Base // 기본: private 상속
// (class Derived : private Base; 와 동일)
{
};
int main()
{
Derived d;
// d.Foo(); // private 상속이라 Base의 public 멤버가 외부에 안 보임
}
struct Base
{
public:
void Foo() {}
};
struct Derived : Base // 기본: public 상속
// (struct Derived : public Base; 와 동일)
{
};
int main()
{
Derived d;
d.Foo(); // public 상속이라 그대로 사용 가능
}
즉,
class -> private 상속이 기본struct -> public 상속이 기본위의 두 가지는 문법적인 차이이고, 그 외의 차이는 대부분 사람들이 이러한 경우에 쓰자고 하는 관례에 가깝다.
public이고, 특별한 캡슐화가 필요 없는 경우struct Vector3
{
float x;
float y;
float z;
Vector3(float x, float y, float z)
: x(x), y(y), z(z) {}
float LengthSquared() const
{
return x*x + y*y + z*z;
}
};
struct Stats
{
int hp;
int mp;
int stamina;
};
사용할 땐 직접 접근해서 사용한다.
Vector3 pos(1.0f, 2.0f, 3.0f);
Stats s{ 100, 50, 30 };
s.hp -= 10; // 바로 접근해도 큰 문제 없음
float len2 = pos.LengthSquared();
class Player
{
public:
Player()
: hp(100), maxHp(100) {}
void TakeDamage(int damage)
{
hp -= damage;
if (hp < 0) hp = 0;
}
void Heal(int amount)
{
hp += amount;
if (hp > maxHp) hp = maxHp;
}
int GetHP() const { return hp; }
private:
int hp;
int maxHp;
};
사용할 땐 멤버 함수를 통해 접근한다.
int main()
{
Player p;
// p.hp = 9999; // 직접 조작 불가
p.TakeDamage(30);
p.Heal(20);
}
C++에서는 struct와 class의 차이가 대부분 접근 지정자(default access) 정도로 단순하지만, Unreal Engine에서는 USTRUCT와 UCLASS 사이에 큰 기능적 차이가 존재한다.
Unreal의 리플렉션 시스템, GC, UObject 생명 주기, Blueprint, 네트워크 등
엔진 전반에 걸쳐 USTRUCT와 UCLASS는 완전히 다르게 동작한다.
대표적인 차이를 정리하면 다음과 같다.
USTRUCT(BlueprintType)
struct FPlayerStats
{
GENERATED_BODY()
UPROPERTY(EditAnywhere)
int HP;
};
UCLASS()
class UMyObject : public UObject
{
GENERATED_BODY()
};
즉,
데이터 중심 = USTRUCT
객체/시스템 = UCLASS
즉, 로직/행동이 필요한 경우 반드시 UCLASS여야 한다.
즉, BP/네트워크/함수 기반 확장이 필요하면 무조건 UCLASS.
UObject*가 UPROPERTY()로 되어 있으면 GC가 해당 객체만 추적USTRUCT()
struct FItem
{
GENERATED_BODY()
UPROPERTY()
UTexture2D* Icon; // GC가 추적
};
UPROPERTY() UObject*를 자동 추적struct = public인 class
구조적으로 거의 동일하며, 대부분 설계/관례로 구분한다.
USTRUCT = 값 타입(데이터), GC 없음, 가벼움
UCLASS = 객체 타입(로직), GC 관리, Blueprint/Network/Reflection 전체 지원