멤버 함수 포인터2

<클래스 내에서 멤버 함수 포인터를 사용하기>

클래스내에서 멤버함수를 사용하는 방법은 간단하다.
State Pattern에 응용할 수 있다. 클래스를 상속 할 필요가 없으므로 간단한 State Pattern 대신 사용하면
편리하다.

코드가 짧으므로 소스로 설명한다.

//1. 멤버 함수 타입 선언

typedef bool ( Command::*CmdType ) ( int id );

 

//2. SetCurState에 Command 객체의 멤버 함수 선언후

//Execute에 의해 멤버 함수를 실행한다.

class Command

{

public:

    Command(){  m_cmdFunc = NULL; }

    virtual ~Command(){};

 

    bool SitDown(int id)

    {

        std::cout << "앉다" << std::endl;

        return true;

    }

 

    void SetCurState( CmdType cmdFunc )

    {

        m_cmdFunc = cmdFunc;

    }

    void Execute()

    {

        (this->*m_cmdFunc)( 0 );

    }

 

protected:

    CmdType  m_cmdFunc;

};

 

//3. 실제 멤버 함수 적용

    Command command;

    command.SetCurState( &Command::SitDown );

    command.Execute();

<문자열을 이용한 멤버 함수 포인터 이용>

이번 장에서는 일반 멤버 함수의 포인터를 std::map에 저장하여 실행해 본다.

typedef bool ( Command::*CmdType ) ( int id );

typedef std::pair<const char*, CmdType>   MakeCmd;

typedef std::map<const char*, CmdType, StriLess >  CmdMap;

실행 할 클래스의 멤버 함수 포인터를 선언한다.
std::map에 입력하기 위한 pair를 만든다.  <문자열, 함수 포인터> 순으로 데이터는 입력된다.
std::map 데이터 타입을 선언한다. StriLess는 비교 클래스이다.

class StriLess: public std::binary_function<const char*, const char*, bool>

{

public:

    result_type operator() (first_argument_type x, second_argument_type y) const

    {

        return _stricmp( x, y ) < 0;

    }

};

StriLess는 대소문자 구분없이 x가 y보다 작은지 비교하는 클래스이다.

 

class Command

{

    CmdMap cmdTable;

public:

    Command(){ m_cmdFunc = NULL;  }

    virtual ~Command(){}

 

    bool SitDown(int id)

    {

        std::cout << "앉다" << std::endl;

        return true;

    }

    bool Walk(int id)

    {

        std::cout << "걷다" << std::endl;

        return true;

    }

    bool Run(int id)

    {

        std::cout << "달리다" << std::endl;

        return true;

    }

 

    void Init();

    void Process( char* str );

 

    void SetCurState( CmdType cmdFunc )
    {

        m_cmdFunc = cmdFunc;

    }

    void Execute()

    {

        if( m_cmdFunc )

            (this->*m_cmdFunc)( 0 );

    }

protected:

    CmdType  m_cmdFunc;

};

 

 

void Command::Init()

{

    cmdTable.insert( MakeCmd( "sit", &Command::SitDown ) );

    cmdTable.insert( MakeCmd( "walk", &Command::Walk ) );

    cmdTable.insert( MakeCmd( "run", &Command::Run ) );

}

 

void Command::Process( char* str )

{

    CmdMap::iterator iter = cmdTable.find( str );

    if( iter != cmdTable.end() )

    {

        (this->*iter->second)( 3 );

    }

}

Command 클래스는 한 개의 객체만 생성 되는걸로 한정한다.
CmdTable cmdTable을 선언한다.
Command::Init()에서 cmdTable에 값을 넣는다.

Command::Process는 게임 루프에서 불려지는 메소드이다.

"sit"을 넘기면 SitDown()이 실행 된다.

(this->*iter->second)( 3 )  문장은 Command 객체의 메소드를 실행한다.

 

소스 : CmdTable1.zip

참조: 롤 플레잉 게임 프로그래밍 (사이버 출판사) 138page