전방 타입 선언

전방 타입 선언 (Forward type declarations)

연결 리스트(linked list)를 만들다 보면, 아직 정의가 끝나지 않은 타입을 가리키는 포인터가 필요한 순간이 찾아와요. 그럴 때 쓰는 게 전방 타입 선언이에요. 어떤 상황에서 필요하고 어떻게 쓰는지 볼게요.

출처: 문서

본문

프로그램은 흔히 레코드의 연결 리스트를 유지해야 해요. 각 레코드는 다음 레코드(그리고 아마 이전 레코드)를 가리키는 포인터를 담고 있죠. 타입 안전성을 위해 이 포인터를 타입이 지정된 포인터(typed pointer)로 정의하는 게 좋아요. 그래야 New 호출로 다음 레코드를 힙에 할당할 수 있거든요. 그러려면 레코드를 대략 이렇게 정의해야 해요:

Type

TListItem = Record

Data : Integer;

Next : ^TListItem;

end;

그런데 이걸 컴파일하려고 하면, 컴파일러는 Next 선언을 만나는 시점에 TListItem 타입이 아직 정의되지 않았다고 불평해요. 당연한 얘기예요. 정의가 아직 파싱되는 중이니까요.

Next 요소를 타입이 지정된 포인터로 만들려면 **전방 타입 선언(Forward type declaration)**을 도입해야 해요:

Type

PListItem = ^TListItem;

TListItem = Record

Data : Integer;

Next : PTListItem;

end;

컴파일러가 참조 대상 타입이 아직 알려지지 않은 타입이 지정된 포인터 선언을 만나면, 그 참조 해석을 나중으로 미뤄요. 이런 포인터 정의가 바로 전방 타입 선언이에요.

참조되는 타입은 같은 Type 블록 안에서 나중에 도입돼야 해요. 포인터 타입 정의와 참조 타입 사이에 다른 블록이 끼어들면 안 돼요. 심지어 Type라는 단어 자체도 다시 나오면 안 돼요. 그건 사실상 새 type 블록을 시작하는 셈이라, 컴파일러가 현재 블록의 모든 미결 선언을 해결해 버리거든요.

대부분의 경우 위 예시처럼 참조 타입의 정의는 포인터 타입 정의 바로 뒤에 따라와요. 전방 정의된 타입은 그 선언 뒤에 오는 어떤 타입 정의에서든 사용할 수 있어요.

참고로 전방 타입 선언은 포인터 타입과 클래스에서만 가능하고, 다른 타입에서는 쓸 수 없어요.

더 알아보기

  • 전방 타입 선언이 왜 필요한지는 포인터 절의 연결 리스트 예시를 보면 이해가 쉬워요.
  • 클래스에서의 전방 선언에 대해서는 객체 지향 관련 절에서 다뤄요.