반응형

CRTP 활용한 싱글톤(Singleton) 만들기

  • 싱글톤: 하나의 객체만 생성 할 수 있게 만드는 디자인 패턴
    • private 생성자
    • 복사와 대입 금지
    • 하나의 객체를 만들어서 리턴하는 static 멤버 함수

단일 Singletone 패턴 클래스

#include <iostream>
using namespace std;

class Cursor
{
private:
    Cursor() {}
public:
    Cursor(const Cursor& c) = delete;
    void operator=(const Cursor& c) = delete;

    static Cursor& getInstance()
    {
        static Cursor instance;
        return instance;
    }

};

int main()
{
    Cursor& c1 = Cursor::getInstance();
    Cursor& c2 = Cursor::getInstance();
}

CRTP 패턴 Singleton 패턴 클래스

#include <iostream>
using namespace std;

template<typename T>
class Singleton
{
protected:
    Singleton() {}
public:
    Singleton(const Singleton& c) = delete;
    void operator=(const Singleton& c) = delete;

    static T& getInstance()
    {
        static T instance;
        return instance;
    }
};

class Mouse : public Singleton<Mouse>
{
};

int main()
{
    Mouse& m1 = Mouse::getInstance();
    Mouse& m2 = Mouse::getInstance();
}

 

CRTP 활용한 Unique한 기반 클래스 만들기

  • 기반 클래스의 static memeber data는 모든 파생 클래스에 의해 공유됨

  • 파생 클래스 별로 다른 static member data가 필요한 경우, 서로 다른 기반 클래스를 사용해야 함

  • CRTP를 사용하면 모든 파생 클래스 별로 다른 타입의 기반 클래스를 만들 수 있음

static 멤버 데이터를 관리하는 단일 클래스

#include <iostream>
using namespace std;

class Object
{
public:
    static int cnt;

    Object() { ++cnt; }
    ~Object() { --cnt; }

    static int getCount() { return cnt; }
};
int Object::cnt = 0;

int main()
{
    Object c1, c2;
    cout << c1.getCount() << endl;
}

static 멤버 데이터를 관리하는 유일한 기반 클래스

#include <iostream>
using namespace std;

template<typename T>
class Object
{
public:
    static int cnt;

    Object() { ++cnt; }
    ~Object() { --cnt; }

    static int getCount() { return cnt; }
};
template<typename T> int Object<T>::cnt = 0;

class Mouse : public Object<Mouse>
{

};

class Keyboard : public Object<Keyboard>
{

};

int main()
{
    Mouse m1, m2;
    Keyboard k1, k2;
    cout << m1.getCount() << endl;
    cout << k1.getCount() << endl;
}
반응형

반응형

CRTP(Cruiously Recurring Template Pattern) 활용

  • 기반 클래스에서 파생 클래스의 이름을 사용할 수 있게 하는 기법

  • 파생 클래스를 만들때 기반 클래스의 템플릿 인자로 파생 클래스 이름을 전달

기준 코드

  • 메인 함수 호출 시 기반 클래스의 OnClick 함수가 호출됨
  • 파생 클래스의 OnClick 함수를 호출하기 위해서는?
#include <iostream>
using namespace std;

class Window
{
public:
    void msgLoop()
    {
        OnClick();
    }
    void OnClick() { cout << "Window OnClick" << endl; }
};

class FrameWindow : public Window
{
public:
    void OnClick() { cout << "FrameWindow OnClick" << endl; }
};

int main()
{
    FrameWindow fw;
    fw.msgLoop(); // OUTPUT : Window OnClick
}

 

구현 코드

  • 비 가상 함수(Non virtual function)를 가상 함수 처럼 동작하게 함
  • 파생 클래스를 만들때 기반 클래스의 템플릿 인자로 파생 클래스 이름을 전달
    • this 포인터를 파생 클래스 타입으로 캐스팅 후 함 수 호출
#include <iostream>
using namespace std;

template<typename T>
class Window
{
public:
    void msgLoop()
    {
        // this 포인터를 파생 클래스인 T 타입으로 캐스팅 후 호출    
        static_cast<T*>(this)->OnClick();
    }
    //가상함수로 만들면 가상함수 테이블이 관리됨
    void OnClick() { cout << "Window OnClick" << endl; }
};

class FrameWindow : public Window<FrameWindow>
{
public:
    void OnClick() { cout << "FrameWindow OnClick" << endl; }
};

int main()
{
    FrameWindow fw;
    fw.msgLoop(); // OUTPUT : FrameWindow OnClick
}
반응형

+ Recent posts