완전한 타입(Complete Type), 불완전한 타입(Incomplete Type)
1. 설명
완전한 타입이란, 해당 컴파일 시점에서 그 타입(구조체(struct), 열거자(enum), 공용체(union), 클래스(class))의 구현(Implement) 정보를 모두 알고 있는 타입을 말합니다.
위 4가지를 제외한 모든 타입은 무조건 완전한 타입입니다.
불완전한 타입이란, 해당 컴파일 시점에서 그 타입의 구현 정보를 알지 못하고, 선언된 정보만 알고 있는 상태를 말합니다.
※ 타입의 어떠한 정보도 알지 못하는건 그냥 알수 없는 타입(unknown type)이나 알수 없는 식별자(unknown identifier) 입니다. 보통 실수로 헤더를 넣지 않거나 했을 때 생깁니다.
2. 예시
#include <stdio.h>
struct Widget;
int main(){
Widget w;
return 0;
}
struct Widget {}; // 실제 구현은 여기서!
Widget 구조체를 전방 선언(forward declaration) 한 후, 바로 사용한다고 가정 해 봅시다.
컴파일러는 위에서 아래로 읽기 때문에, main() 안에서는 Widget 객체의 생성자에 대한 정보를 전혀 알 수 없습니다.
그래서 컴파일 하면 다음과 비슷한 에러가 나오며 실패하게 됩니다.
/Users/yonggyulee/CLionProjects/playground/main.cpp:6:10: error: variable has incomplete type 'Widget'
Widget w;
^
/Users/yonggyulee/CLionProjects/playground/main.cpp:3:7: note: forward declaration of 'Widget'
class Widget;
이를 해결하려면, 구현을 실제 사용 시점 이전에 작성해야 합니다.
#include <stdio.h>
struct Widget;
struct Widget {};
int main(){
Widget w;
return 0;
}
※ 함수의 전방 선언(Function forward declaration)은 함수에 서명(signature)을 모두 담고 있으므로, 구현 이전에 호출해도 알맞은 용법입니다.
3. 예외
포인터는 해당 타입이 불완전 하더라도 선언할 수 있습니다.
#include <stdio.h>
#include <cstdlib>
struct Widget;
void initWidget(Widget** w);
int main(){
Widget* w;
initWidget(&w);
return 0;
}
struct Widget {}; // 실제 구현은 여기서!
void initWidget(Widget** w) {
// C
*w = (Widget*) malloc(sizeof(Widget));
}
※ C 언어를 예시로 들었지만, C++ 에서도 동일하게 가능합니다.
불완전한 타입에 대한 포인터를 이용하는 디자인이 PImple 기법입니다.
'C & C++ > 개념(Concept)' 카테고리의 다른 글
C/C++ 개념: 전방 선언(forward declaration) (0) | 2020.11.12 |
---|