본문 바로가기
Study(Game)/C++ DirectX11

[DirectX11] 02 - Singletone 패턴

by chunkind 2026. 5. 3.

싱글톤 패턴 1

Engine > pch.h

// pch.h: 미리 컴파일된 헤더 파일입니다.
// 아래 나열된 파일은 한 번만 컴파일되었으며, 향후 빌드에 대한 빌드 성능을 향상합니다.
// 코드 컴파일 및 여러 코드 검색 기능을 포함하여 IntelliSense 성능에도 영향을 미칩니다.
// 그러나 여기에 나열된 파일은 빌드 간 업데이트되는 경우 모두 다시 컴파일됩니다.
// 여기에 자주 업데이트할 파일을 추가하지 마세요. 그러면 성능이 저하됩니다.

#ifndef PCH_H
#define PCH_H

// 여기에 미리 컴파일하려는 헤더 추가
#include "framework.h"

//new
#include <Windows.h>

#endif //PCH_H

 

Engine > 01. Engine > CEngine.h (new)

#pragma once


class CEngine
{
// 데이터 영역 메모리 : 전역 변수
// 프로세스 시작할때 초기화
// 프로세스 종료시 해제
// 프로세스가 실행도중 상시 유지되는 메모리
private:
	static CEngine* g_This;

private:
	HWND	m_hMainWnd;

public:
	// 정적 맴버함수 : 객체가 없어도 호출 가능
	static CEngine* GetInst()
	{
		if (g_This == nullptr) {
			g_This = new CEngine;
		}
		return g_This;
	}

	static void Destroy() {
		delete g_This;
		g_This = nullptr;
	}
private:
	CEngine();

};

 

Engine > 01. Engine > CEngine.cpp (new)

#include "pch.h"
#include "CEngine.h"

CEngine* CEngine::g_This = nullptr;

CEngine::CEngine() {

}

 

Client > Client.cpp

...
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    //old
    //int value = Add(10, 20);

    MyRegisterClass(hInstance);

    hInst = hInstance;
    
    HWND hWnd = CreateWindowW(L"Test", L"MyGame", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    
    if (!hWnd)
    {
        return FALSE;
    }
    
    ShowWindow(hWnd, true);
    UpdateWindow(hWnd);

    //new
    // CEngine 객체 초기화
    CEngine* pEngine = CEngine::GetInst();

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLIENT));
    MSG msg;

    while (true)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            if (WM_QUIT == msg.message)
                break;

            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        else
        {
            // Game Engine 실행

        }
    }

    //new
    CEngine::Destroy();

    return (int) msg.wParam;
}
...

 

싱글톤 패턴 2

Engine > 01. Engine > CEngine.h (new)

#pragma once


class CEngine
{
public:
	static CEngine* GetInst() {
		// 데이터 영역 메모리를 사용한다.
		// 함수호출이 끝났어도 데이터는 삭제되지 않는다.
		static CEngine mgr;
		return &mgr;
	}
    
private:
	CEngine();
};

 

Engine > 01. Engine > CEngine.cpp (new)

#include "pch.h"
#include "CEngine.h"

//old
//CEngine* CEngine::g_This = nullptr;

CEngine::CEngine() {

}

 

Client > Client.cpp

...
    }

    //new
    //CEngine::Destroy();

    return (int) msg.wParam;
}

 

 

이방식은 Destroy() 가 필요없다.

프로그램 도중에는 삭제 시킬수 없기 때문에..

 

디폴트 복사생성자 문제

Client > Client.cpp

CEngine* pEngine = CEngine::GetInst();
CEngine e = *pEngine;

 

우리가 안막아두었던 default 복사생성자때문에 위에 코드로 싱글톤도 객체생성이 가능해버린다.

 

Engine > 01. Engine > CEngine.h

#pragma once

class CEngine
{
//new
private:
	HWND m_hMainHwnd;
	POINT m_Resolution;

public:
	static CEngine* GetInst() {
		static CEngine mgr;
		return &mgr;
	}

private:
	CEngine();

//new
public:
	CEngine(const CEngine& _origin)
		: m_hMainHwnd(_origin.m_hMainHwnd)
		, m_Resolution(_origin.m_Resolution)
	{

	}
};

위 코드처럼 생긴 CEngine 이 있기때문에 복사 생성자가 생략된 거다.

public:
	//old
	//CEngine(const CEngine& _origin)
	//	: m_hMainHwnd(_origin.m_hMainHwnd)
	//	, m_Resolution(_origin.m_Resolution)
	//{

	//}
	//new
	CEngine(const CEngine& _origin) = delete;
};

 

위와 같이 기본 복사생성자를 사용하지 못하게 막자.

Client > Client.cpp

CEngine* pEngine = CEngine::GetInst();
//old
//CEngine e = *pEngine;

 

Engine > 01. Engine > CEngine.h

private:
	CEngine();

//old
//public:
	CEngine(const CEngine& _origin) = delete;
반응형