[MFC 기본] 필요 C++ 이론과 Event Loop 원리

Jin Hur·2022년 6월 19일
0

1. 자료구조와 내부 로직과 UI 관련 로직을 분리한다.

addNewMember() <-> addNewNode()

2. while(출력 및 사용자 입력) { switch .. }

while 문 == Event Loop(이벤트 루프)

void main() {
    int nMenu = 0;
    LoadList(DATA_FILE_NAME);
    
    // Event Loop(이벤트 루프)
    while( (nMenu = PrintMenuUI()) != 0 ) {
        switch(nMenu) {
        case 1:
            Add();
            break;
        case 2:
            Search();
            break;
        ...
        ...
    }
    ...
}

Event Loop

source: https://flylib.com/books/en/2.906.1.18/1/

3. 객체지향적으로 설계한다.

  • CMyList // 자료구조 관련 코드
    • CMyList(void)
    • AddNewNode(..)
    • FindNode(..)
    • PrintAll(void)
    • RemoveNode(..)
    • ..
  • CUserData // 자료구조 관련 코드
    • CUserData(void)
    • GetName(void)
    • GetNext(void)
    • ..
  • CUserInterface // UI 관련 코드
    • CuserInterface(..)
    • Add(void)
    • PrintMenuUI(void)
    • Run(void) // 이벤트 루프에 해당
    • ..
  • Main 함수
    객체지향적으로 잘 설계하면 메인함수가 메우 간단해진다.
int _main(int argc, _TCHAR* argv[]) {
    // 초기화
    CMyList DB;
    CUserInterface UI(DB);
    // 트리거 
    UI.Run()	// 이벤트 루프
    return 0;
}

=> 객체지향화를 잘 할 수록 메인함수의 코드는 간결해진다.

cf) MFC에는 Main 함수가 개발자에게 감추어져 있다.

4. 파생 클래스의 생성자에서는 상위 클래스의 멤버를 초기화하지 않도록 한다.

파생 클래스의 생성자가 호출되면, 가장 상위에 있는 클래스의 생성자를 호출하게 되고, 이후 아래 단계의 생성자들이 차례대로 실행된다. 이러한 흐름속에서 파생 클래스의 생성자에선 파생 클래스에 정의된 멤버만 초기화하도록 한다.

MFC에서 이 약속을 어기실 코드가 꼬일 확률이 높아진다.

5. 가상 함수를 오버라이딩하여 기능을 구현한다. 가상 함수의 호출은 프레임워크의 흐름안에 일어난다(개발자가 개입하지 못함).

#include <iostream>
using namespace std;


class A {	// 프레임워크 코드
public:
	void mainfunc() {	// 주요 제어권을 가진 로직
		// 가상 함수 호출! (Called by framework)
		func();		// <= 개발자가 오버라이딩하여 기능을 구현한다. 
	}

	virtual void func() {
		cout << "Default" << endl;
	}
};

class B : public A {	// Version 1 코드
public:
	void func() {
		cout << "Version 1 기능" << endl;
	}
};

class C : public B {	// Version 2 코드
public:
	void func() {
		cout << "Version 2 기능" << endl;
	}
};

// 프레임워크 안 Main 함수
int main() {
	A* aptr = new C();
	aptr->mainfunc();

	return 0;
}

기존의 기능을 그대로 가져갈 수도 있다.

class A {	// 프레임워크 코드
public:

	void mainfunc() {	// 주요 제어권을 가진 로직
		// 가상 함수 호출! (Called by framework)
		func();		// <= 개발자가 오버라이딩하여 기능을 구현한다. 
	}

	virtual void func() {
		cout << "Default" << endl;
	}
};

class B : public A {	// Version 1 코드
public:
	void func() {
		A::func();	// 기본 기능을 그대로 가져간다.
		cout << "Version 1 기능" << endl;
	}
};

class C : public B {	// Version 2 코드
public:
	void func() {
		B::func();	// 이전의 기능을 그대로 가져간다. 
		cout << "Version 2 기능" << endl;
        // 기존 코드와 현재 코드의 순서 관계 또한 중요 고려사항이다. 
	}
};

0개의 댓글