본문 바로가기

코딩/C++,C

[C++]클래스 사이의 교차적인 포함관계

m.blog.naver.com/PostView.nhn?blogId=jinhuk1313&logNo=220618867607&proxyReferer=https:%2F%2Fwww.google.com%2F

 

[C++]클래스 사이의 교차적인 연관 관계

학과에서 진행하는 동계 코딩 캠프에 튜터로 참여하게 되면서, 튜티들이 풀 문제에 대한 해답을 준비하다 ...

blog.naver.com

교차적인 연관 관계

 

 

 전처리문 #ifndef #define을 통해 헤더 파일을 중복하여 읽지 않게 하였고, 클래스 A는 클래스 B의 인스턴스를 멤버 변수로 갖고, 클래스 B는 클래스 A의 인스턴스를 멤버 변수로 갖게 클래스 A, B를 정의하였다. 클래스 다이어그램으로 나타내면 아래와 갖다.

 전혀 문제될 것이 없어 보인다. 하지만 컴파일을 하게 되면 다음과 같은 컴파일 오류가 발생한다.
error C2146: 구문 오류 : ';'이(가) 'a' 식별자 앞에 없습니다.
error C4430: 형식 지정자가 없습니다. int로 가정합니다. 참고: C++에서는 기본 int를 지원하지 않습니다.
error C2236: 예기치 않은 토큰 'class'입니다. ';'이 없습니다.
error C2143: 구문 오류 : ';'이(가) '{' 앞에 없습니다.
error C2447: '{' : 함수 헤더가 없습니다. 이전 스타일의 형식 목록입니까?
error C2065: 'A' : 선언되지 않은 식별자입니다.
error C2146: 구문 오류 : ';'이(가) 'a' 식별자 앞에 없습니다.
error C2065: 'a' : 선언되지 않은 식별자입니다.
 
 전혀 도움되지 않는 컴파일 오류 메시지가 출력되었다. 이런 경우 보통은 정의한 클래스 A, B를 찾을 수 없어 발생하는 오류이다. 그렇다면 왜 찾을 수 없을까? 컴파일러가 A.h와 B.h를 컴파일하는 과정을 살펴보자.
1) 컴파일러가 A.h 파일을 컴파일하려 한다.
2) A_H가 존재하지 않다면, A_H를 정의한다.
3) B.h 헤더파일을 포함시킨다.
4) 포함시키려는 파일 B.h를 컴파일한다.
5) B_H가 존재하지 않기 때문에 B_H를 정의한다.
6) A.h 헤더파일을 포함시킨다.
7) 다시 A.h파일로 왔다. 하지만, 2 번에서 A_H를 정의했기때문에 
#ifndef~#endif까지의 내용은 무시된다.
(즉, 클래스 A를 정의하지 않는다.) 
8) 6 번에서 A.h 헤더파일을 포함시켰지만, 클래스 A를 알 수 없기 때문에 
컴파일 에러 발생
 
 이것으로 보면 헤더 파일을 한 번만 읽기 때문이라고 생각할 수도 있지만, 만약 #ifndef를 사용하지 않는다면  헤더파일을 두 번 읽기 때문에 클래스 중복 선언으로 컴파일 오류가 발생하게 된다.

 

해결 방법
 문제는 헤더 파일을 포함하는 과정에서 발생되기 때문에, 헤더 파일을 포함시키지 않고, 해당 클래스가 존재한다고 명시만 해놓는 것으로 문제를 해결할 수 있다.   

 

 위와 같이 전처리문 #include"A.h" 를 사용하는 것 대신, class A로 클래스 A가 존재한다는 것을 알려주어 문제를 해결할 수 있다. 포인터로 선언한 이유는 컴파일러가 클래스 A가 무엇인지 모르는 상태이므로, 객체의 크기를 알 수 없기 때문에 컴파일 오류가 발생하는 것을 막기 위해서이다. 
 단, 주의해야할 점은 클래스 구현 부분(.cpp 파일)에서는 헤더파일을 포함시켜주어야 한다.