class vs struct
struct
의 사용법은 다음과 같다.
// 구조체 정의
struct data
{
int a;
char b;
void foo() { ... }
};
// 구조체의 변수 선언
data mydata;
// 함수 호출
mydata.foo();
class
의 사용법은 다음과 같다.
// 클래스 정의
class obj
{
int a;
char b;
void foo() { ... }
};
// 클래스의 변수 선언
obj myobj;
// 함수 호출
myobj.foo();
둘 다 똑같이 멤버 변수와 메서드를 가질 수 있다. 하지만 main
함수에서 호출해보면 class
는 함수 호출이 되지 않는다. 왜냐하면 class
는 기본 접근 지정자(access modifier)가 private
이고, struct
는 public
이기 때문이다.
이 외에는 차이가 없다. 하지만 코딩 컨벤션에 따라서 둘은 다르게 사용된다.
struct
는 간단한 데이터들의 모음인 Plain Old Data(POD)로 사용한다. 예를 들면 다음과 같다.
struct mystruct
{
// 데이터의 모음
int data;
int x;
int y;
/* 별 다른 로직을 구현하지 않는다! */
}
이 외에 private
, protected
멤버나 여러 로직을 추가 구현해야 할 경우는 class
를 사용한다.
요약하자면, 언어 상의 차이는 기본 접근 지정자가 struct
는 public
, class
는 private
로 다른 것 뿐이다. 하지만 대부분의 C++ 코딩 컨벤션에서는 struct
는 간단한 데이터의 모음으로, class
는 추가적인 로직이 필요한 객체로 구분해서 사용하고 있다.
번외: C# 에서
그렇다면 C#에서는 어떨까? C#에서도 struct
와 class
는 멤버 변수와 메서드를 동일하게 가질 수 있다.
그러나 중요한 차이점이 있다.
struct | class |
값 타입(Value type)이다. | 참조 타입(Reference type)이다. |
스택에 할당된다. | 힙에 할당된다. |
상속이 불가능하다. | 상속이 가능하다. |
값 타입과 참조 타입이 뭘까?
값 타입은 함수의 매개변수로 전달했을 때 원본 값의 복사본을 전달한다.
그러므로 값 타입은 함수 내에서 전달받은 값을 변경해도 원본에는 영향을 주지 못한다.
또한 전달될 때 스택영역에 구조체의 크기만큼 할당하기 때문에, 크기가 크면 스택 사용량도 그만큼 늘어난다.
참조 타입은 원본을 참조할 수 있는 주소를 전달한다.
참조 타입은 해당 주소에 있는 원본을 수정하기 때문에 영향을 줄 수 있다. C#이나 JAVA에서 클래스를 매개변수로 넘겨주면 기본적으로 참조 타입으로 넘어가기 때문에, 함수 내에서 수정이 가능한 것이다.
C++에서 참조 타입으로 넘겨주는 &
나 *
를 사용한 pass by reference과 동일하다.
또 처음엔 힙에 할당하고 이후 전달될 땐 이에 대한 주소 값만을 전달하므로 클래스의 크기가 커도 스택 사용량은 늘지 않는다.
이것에 대해서는 나중에 C++ 코드로 다루면서 더 자세한 글을 쓸 예정이다.
Unity에서는 Vector3
또는 Quaternion
등을 구조체로 사용하고 있다. 일반적으로 new
키워드를 사용하면 힙에 할당되는 것과 달리, 스택에 할당된다. C#이 통일성 때문에 지원하는 것이라고 하는데... 오히려 좀 혼동되는 면이 없잖아 있다.
이들을 왜 구조체로 정의했을까? 좌표나 회전값에 대한 데이터 모음이기 때문이다. 하지만 데이터만 있는 대신에, 컨벤션을 해치지 않는 선에서 몇 가지 유틸리티 함수를 지원해 편의성을 제공하고 있다.