C++/이게 왜 돼 ❔❔❔

[MFC] 다른 클래스에서 다이얼로그의 컨트롤 사용하기 ( 순환참조 피하기 )

트럼프 2022. 3. 24. 03:11

상황은 대충 이러할 때 쓸 수 있다.

사진 1

메인 다이얼로그, 송 수신 클래스가 있다.

구분을 위해 송신 '클래스', 수신 '클래스'라고 명명했지만

다이얼로그 클래스라고 생각해도 되고 다이얼로그가 연결돼있지 않은 일반 클래스라고 생각해도 된다.

본인은 메인 다이얼로그-클래스 관계로 코딩함. 자녀 다이얼로그의 클래스도 클래스이기 때문에 뭐 상관없다고 보고 그냥 포스팅

 

어쨌든

메인 다이얼로그(메인 클래스)에서 송신 클래스, 수신 클래스를 생성, 삭제, 조작한다.

즉, <사진 2>처럼 메인 다이얼로그는 송신 클래스와 수신 클래스를 알고 있는 상태이다.

알고 있는 상태라는 것은 당연히 메인 다이얼로그의 헤더에 각 클래스가 인클루드 된 상태라는 것

사진 2

 

그렇다면 다이얼로그의 클래스가 아닌

다른 클래스(ChildDlg)에서 다이얼로그의 멤버 변수를 사용하거나, 컨트롤을 제어하고 싶을 때

단순히 헤더에 다이얼로그를 include 하고 멤버 변수를 꺼내 쓰면 되는 거 아닌가?라고 생각할 수 있다.

사진 3

<사진 3>에서 알 수 있듯이 화살표를 보자

ChildDlg에서 메인 다이얼로그를 include하면

이미 메인 다이얼로그가 ChildDlg를 이미 알고 있는 상태이기 때문에 양방향의 화살표가 생겨버려서

순환 참조 에러가 날 수 있다.

 

아래 코드처럼 하면 된다.

편한 메모를 위해 부모 다이얼로그는 ParentDlg, 자녀 다이얼로그는 ChildDlg라 명명한다.

 

 

 

코드

 

<자녀 클래스>

1. 자녀 클래스에서 부모클래스를 선언해준다.

이때, 부모 다이얼로그의 헤더를 include는 하지 않는다.

// ChildDlg.h

class CParentDlg;	// 클래스 생성

class CChildDlg
{
	...
}

이런 식으로 따로 빼서 CParentDlg를 선언하고

 

 

2. 클래스와, 함수, 변수를 하나 씩 만든다.

// ChildDlg.h

class CParentDlg;

class CChildDlg
{
	CParentDlg* m_pParent;
	void Set_Wnd(CWnd* arg_pParent);
}

 

3. 이어서 자녀 다이얼로그의 cpp파일은 아래와 같이 작성한다.

// ChildDlg.cpp

#include <ChildDlg.h>
#include <ParentDlg.h>  // 여기서(cpp파일) 부모의 헤더를 추가한다.

void CChildDlg::Set_Wnd(CWnd* arg_pParent)
{
	this->m_pParent = (CParentDlg *)arg_pParent
}

이렇게 만든 Set_Wnd함수를 메인에서 사용한다면,

m_pParent로 메인 핸들을 받아와서 메인 다이얼로그의 멤버 변수나 컨트롤을 사용할 수 있다.

 

 

<부모 다이얼로그>

1. 부모 다이얼로그의 헤더에 자녀 클래스를 include한다.

// CParent.h

#include "Client.h"

 

2. 부모 다이얼로그에서 자녀 클래스를 선언한다.

// CParent.h

public:
	CChildDlg* pChild;

 

3. 클래스를 생성한 뒤, Set_Wnd함수를 사용하여 자신의 핸들을 넘겨준다.

// CParent.cpp

pChild = new CChildDlg();   // 생성

pChild->Set_Wnd(this);      // 넘겨주기

 

 

 

결과

 

자녀 다이얼로그에서 아래와 같이 메인 다이얼로그의 멤버 변수를 사용하면 된다.

// ChildDlg.cpp

(m_pParent->m_lst).InsertItem(nIndex, strIndex);

m_pParent->m_lst.InsertItem(nIndex, strIndex); 이런 식으로 써도 잘 작동되는데 가독성 때문에 괄호 붙였다.