728x90

안녕하세요!
이번 글에서는 클래스의 상호참조에서 발생하는 문제를 해결하는 방법에 대해 알아보겠습니다.
클래스 상호참조 시 컴파일러는 [C3646 알수없는 재정의 지정자입니다.], [C4430 형식 지정자가 없습니다. int로 가정합니다.], [C2061 구문오류 : 식별자]등 모호한 에러코드를 남겨 원인을 찾기 힘들게 합니다.
이럴 때 당황하지 않고 상호참조를 우회하여 에러를 해결하는 방법을 제시해 드리겠습니다.
상호참조
- 클래스 간의 상호참조는 헤더 파일의 순환 참조 문제를 일으킬 수 있습니다.
- 이러한 문제를 해결하기 위해 전방선언을 사용할 수 있습니다.
- 전방선언은 클래스를 선언하기 전에 해당 클래스의 존재를 컴파일러에 알려주는 역할을 합니다.
- 이를 통해 클래스 간의 상호참조를 우회할 수 있습니다.
상호참조 우회방법
- 헤더파일에는 클래스를 직접참조 하지않고 전방선언만 해주고, 코드파일에서 클래스를 직접 참조해 주는 방법으로 상호참조를 우회할 수 있습니다.
- 예를 들어 A 클래스와 B 클래스가 상호참조하는 상황을 가정해 봅시다.
- A 클래스의 헤더 파일에는 B 클래스를 전방선언하고, B 클래스의 헤더 파일에는 A 클래스를 전방선언합니다.
- 이렇게 하면 각 클래스는 각자의 내부내용은 모르지만 클래스가 존재한다는 정도는 알 수 있습니다.
- 함수의 매개변수가 아닌 멤버객체로 사용할 경우 전방선언으로는 상대 클래스의 내부내용을 모르는 상태이므로 상대 클래스의 객체를 멤버로 사용할 수 없기 때문에 클래스의 포인터를 사용합니다.
- 해당 객체의 주소값을 받아 포인터 멤버변수에 저장하거나, 함수호출 시 매개변수에 객체의 주소값을 받아서 처리하면 상호참조를 해결할 수 있습니다.
<상호참조 에러발생 예시>
1. A클래스의 헤더파일(A.h)
//B클래스의 헤더파일을 참조
#include "B.h"
class A
{
private:
//B클래스의 객체
B m_classB;
public:
//매개변수로 B객체를 받아 동작
void doSomethingWithB(B b);
};
2. B클래스의 헤더파일(B.h)
//A클래스의 헤더파일을 참조
#include "A.h"
class B
{
private:
//A클래스의 객체
A m_classA;
public:
//매개변수로 A객체를 받아 동작
void doSomethingWithA(A a);
};
- 위의 예시에서 각 클래스는 각각의 헤더파일 내에서 서로를 상호참조 하고 있어 컴파일 오류를 일으키게 됩니다.
<상호참조 우회 예시>
1. A클래스의 헤더파일(A.h)
// 전방선언
class B;
class A
{
private:
//B클래스를 멤버변수로 사용하기 위한 포인터
B* m_pClassB;
public:
//B클래스의 주소를 매개변수로 받아 처리
void doSomethingWithB(B* b);
};
2. B클래스의 헤더파일(B.h)
// 전방선언
class A;
class B
{
private:
//A클래스를 멤버변수로 사용하기 위한 포인터
A* m_pClassA;
public:
//A클래스의 주소를 매개변수로 받아 처리
void doSomethingWithA(A* a);
};
3. A클래스의 코드파일(A.cpp)
#include "A.h"
#include "B.h"
A::A()
{
//B의 포인터 멤버변수에 객체를 동적할당.
m_pClassB = new B();
}
void A::doSomethingWithB(B* b)
{
// B 클래스에 대한 작업 수행
}
4. B클래스의 코드파일(B.cpp)
#include "B.h"
#include "A.h"
B::B()
{
//A의 포인터 멤버변수에 객체를 동적할당
m_pClassA = new A();
}
void B::doSomethingWithA(A* a)
{
// A 클래스에 대한 작업 수행
}
- 위의 예제에서 A 클래스와 B 클래스는 상호참조를 해야 하지만, 각각의 헤더 파일에서 상대 클래스에 대한 전방선언을 추가하여 순환 참조를 방지합니다.
- 이렇게 하면 컴파일러는 클래스의 존재를 인식하고, 포인터를 사용하여 서로를 참조할 수 있습니다.
요약
- 전방선언을 사용하여 클래스 간의 상호참조 문제를 해결하면 컴파일 시 순환 참조 에러가 발생하지 않으며, 클래스의 선언과 정의를 분리할 수 있습니다.
- 이를 통해 코드의 가독성을 향상시키고 유지보수성을 높일 수 있습니다.
- 그러나 전방선언은 클래스 멤버에 대한 접근이 불가능하므로, 포인터를 사용하여 상호작용해야 합니다.
감사합니다!
728x90
'[C++] > 프로그래밍 기초' 카테고리의 다른 글
[C++] 프로그래밍 기초 : 삼항 연산자 (16) | 2023.06.24 |
---|---|
[C++] 프로그래밍 기초 : SOLID원칙 (30) | 2023.06.19 |
[C++] 정적(Static)변수 (42) | 2023.06.16 |
[C++] 프로그래밍 기초 : 전역변수 (31) | 2023.06.16 |
[C++] 프로그래밍 기초 : 포인터 연산 (49) | 2023.06.12 |