struct vs class / 구조체 클래스 차이점 정리

서론

structclassC/C++를 배우는 과정에서 많이 헷갈릴 부분이기도 하다. C에서는 struct만 정의되어 있고 class는 정의되어 있지 않은데 C++에서는 두가지 다 정의되어 있다. 참고로 Go의 경우는 구조체만 정의해서 사용하고 있기 때문에 명확하게 개념을 정리하고 가는 것이 좋겠다.

C에서의 struct (구조체)

"C/C++ 프로그래밍 언어에서 구조화 된 데이터를 처리할 때 struct를 사용하는데 이를 구조체라고 한다." - 위키피디아
구조체는 C에서 처음 정의되었던 개념이기에 C로 돌아가보자. 구조체는 내부에 공통적으로 사용하기를 원하는 변수들을 담는 컨테이너와 같다. 다음 예제 코드를 보면,

struct myStruct{
    int a;
    char b;
    short c;
};

int main()
{
    struct myStruct newStr;
    newStr.a = 1;

    return 0;
}

구조체 내의 변수 a에 새로 정의된 구조체명 newStr을 사용하여 접근할 수 있다. 이와 같이 구조체명 안에 묶여진 변수들을 효율적으로 관리할 수 있다.

C++의 class (클래스)

클래스의 변수는 필드(field) 또는 멤버 변수(Member variable)로, 함수는 메소드(method)라고 불린다.

이게 무슨 말인지 모르겠다면? **이 글**을 먼저 읽고 오자.

class myClass{
    int a;
    char b;
    short c;

public:
    myClass();
    ~myClass();
};

클래스는 public 지시어를 통해서 해당 필드나 메소드를 클래스 외부에서 참조할 수 있는지 여부를 결정한다. 또한 Constructor와 Destructor가 정의된다(만약 클래스 내부에 명시되어 있지 않다면 컴파일러가 인스턴스 생성 시 정의한다).

C++의 struct

그런데 여기서 의문점이 들 것이다(C++를 정확히 공부했다면 반드시 의문이 들어야 한다).

  • C++에서는 구조체도 메소드를 정의할 수 있는데, 그럼 클래스와 다른 점이 없는 것 아닌가?

아래 예제를 보자.

struct myStruct
{
    int a;
    myStruct();
    ~myStruct();

private:
    char b;
    short c;
}

위 예제를 보면, 구조체에서는 필드에 대한 접근이 기본적으로 가능하다. 또한, C++의 구조체는 클래스와 마찬가지로 Constructor와 Destructor가 정의된다.

결론

이상 세 가지 코드를 통해 얻은 결론을 정리하면 다음과 같다.

  • C의 구조체는 변수만을 멤버로 가진다.
  • C++의 구조체는 변수와 함수를 모두 멤버로 가지지만, 멤버에 대한 접근이 기본적으로 가능하다(public이다).
  • C++의 클래스는 변수와 함수를 모두 멤버로 가지지만, 멤버에 대한 접근이 기본적으로 불가능하다(private이다).

글의 내용 중 이해가 되지 않는 부분이 있거나, 잘못된 부분이 있으면 댓글로 남겨주시면 감사하겠습니다 :D

Appendix. Go에서의 struct

Go의 경우에는 독특한 구조체를 정의하고 있다. 먼저 아래 예제를 보자.

type Rect struct {
    width, height int
}

func (r Rect) area() int {
    return r.width * r.height   
}

먼저 type 지시어를 통해 Rect라는 구조체를 정의하고 있는데, 내부에는 필드만이 존재한다. 그러면 Go에서는 구조체 메소드를 정의할 수 없는 것인가? Go는 구조체 외부에 메소드를 따로 정의한다. Receiver라고 부르는 (r Rect)로 소속 구조체를 명시하고 메소드를 정의하고 있는데, 여기서 rRect의 앞글자로, Receiver 이름은 이와 같이 보통 구조체의 맨 앞글자를 소문자로 나타낸다. 해당 메소드의 호출은 main함수에서 다음과 같이 가능하다.

func main() {
    rect := Rect{10, 20}
    area := rect.area()
    println(area)
}

참고