728x90

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이고, structpublic이기 때문이다.
이 외에는 차이가 없다. 하지만 코딩 컨벤션에 따라서 둘은 다르게 사용된다.

struct는 간단한 데이터들의 모음인 Plain Old Data(POD)로 사용한다. 예를 들면 다음과 같다.

struct mystruct
{
    // 데이터의 모음
    int data;
    int x;
    int y;
    /* 별 다른 로직을 구현하지 않는다! */
}

이 외에 private, protected멤버나 여러 로직을 추가 구현해야 할 경우는 class를 사용한다.

요약하자면, 언어 상의 차이는 기본 접근 지정자가 structpublic, classprivate로 다른 것 뿐이다. 하지만 대부분의 C++ 코딩 컨벤션에서는 struct는 간단한 데이터의 모음으로, class는 추가적인 로직이 필요한 객체로 구분해서 사용하고 있다.

번외: C# 에서

그렇다면 C#에서는 어떨까? C#에서도 structclass는 멤버 변수와 메서드를 동일하게 가질 수 있다.

그러나 중요한 차이점이 있다. 

struct class
값 타입(Value type)이다. 참조 타입(Reference type)이다.
스택에 할당된다. 힙에 할당된다.
상속이 불가능하다. 상속이 가능하다.

값 타입과 참조 타입이 뭘까?

 

값 타입은 함수의 매개변수로 전달했을 때 원본 값의 복사본을 전달한다. 

그러므로 값 타입은 함수 내에서 전달받은 값을 변경해도 원본에는 영향을 주지 못한다.

또한 전달될 때 스택영역에 구조체의 크기만큼 할당하기 때문에, 크기가 크면 스택 사용량도 그만큼 늘어난다. 

 

참조 타입은 원본을 참조할 수 있는 주소를 전달한다.

참조 타입은 해당 주소에 있는 원본을 수정하기 때문에 영향을 줄 수 있다. C#이나 JAVA에서 클래스를 매개변수로 넘겨주면 기본적으로 참조 타입으로 넘어가기 때문에, 함수 내에서 수정이 가능한 것이다.

C++에서 참조 타입으로 넘겨주는 &*를 사용한 pass by reference과 동일하다.

또 처음엔 힙에 할당하고 이후 전달될 땐 이에 대한 주소 값만을 전달하므로 클래스의 크기가 커도 스택 사용량은 늘지 않는다. 

이것에 대해서는 나중에 C++ 코드로 다루면서 더 자세한 글을 쓸 예정이다.

 

Unity에서는 Vector3또는 Quaternion등을 구조체로 사용하고 있다. 일반적으로 new 키워드를 사용하면 힙에 할당되는 것과 달리, 스택에 할당된다. C#이 통일성 때문에 지원하는 것이라고 하는데... 오히려 좀 혼동되는 면이 없잖아 있다. 

 

이들을 왜 구조체로 정의했을까? 좌표나 회전값에 대한 데이터 모음이기 때문이다. 하지만 데이터만 있는 대신에, 컨벤션을 해치지 않는 선에서 몇 가지 유틸리티 함수를 지원해 편의성을 제공하고 있다.

728x90