전체 코드


1. 함수 포인터(Function Pointer)

함수 포인터는 함수를 가리키는 포인터입니다.
일반적인 포인터가 변수의 주소를 저장하는 것처럼, 함수 포인터는 함수의 주소를 저장하고 이를 호출할 수 있습니다.

1.1 함수 포인터 기본 예제

#include <iostream>
using namespace std;

void HelloWorld()
{
    cout << "Hello World" << endl;
}

int main()
{
    // 1) 함수 포인터 선언
    void (*pfunc)(void);

    // 2) 함수 포인터에 HelloWorld 함수 할당
    pfunc = &HelloWorld;

    // 3) 함수 포인터를 사용하여 HelloWorld 호출
    (*pfunc)();  // 또는 pfunc();

    return 0;
}

📌 코드 설명

  • void (*pfunc)(void);pfunc는 반환 타입이 void이고 매개변수가 없는 함수를 가리킬 수 있는 함수 포인터입니다.
  • pfunc = &HelloWorld; → 함수 포인터에 HelloWorld 함수 주소를 저장합니다. (&는 생략 가능)
  • (*pfunc)(); → 함수 포인터를 사용하여 HelloWorld 함수를 호출합니다.

1.2 함수 포인터의 한계

void HelloNumber(int number)
{
    cout << "Hello Number: " << number << endl;
}
  • 함수 포인터를 사용하려면 매개변수의 개수와 반환 타입이 정확히 일치해야 합니다.
  • 예를 들어, HelloWorld()는 매개변수가 없고 HelloNumber(int)int를 받으므로, HelloWorld를 가리키던 pfuncHelloNumber를 할당할 수 없습니다.
  • 즉, 함수 포인터는 시그니처(Signature)가 정확히 일치해야 한다는 제한이 있습니다.

2. 함수 객체(Functor)

함수 객체(Functor)란 함수처럼 동작하는 객체를 의미합니다.
이는 연산자 오버로딩을 통해 객체를 함수처럼 호출할 수 있도록 만듭니다.

2.1 함수 객체 기본 예제

#include <iostream>
using namespace std;

class Functor
{
public:
    // () 연산자 오버로딩 (Functor 호출 시 실행될 코드)
    void operator()()
    {
        cout << "Functor Test" << endl;
        cout << _value << endl;
    }

    // 정수를 매개변수로 받아 상태를 변경하는 Functor
    bool operator()(int num)
    {
        cout << "Functor(int) Test" << endl;
        _value += num;
        cout << _value << endl;
        return true;
    }

private:
    int _value = 0;
};

int main()
{
    Functor functor;  // Functor 객체 생성

    functor();  // () 연산자 오버로딩으로 인해 함수처럼 호출 가능
    bool result = functor(3);  // functor(3) -> operator()(int num) 실행

    return 0;
}

📌 코드 설명

  • void operator()()() 연산자를 오버로딩하여 객체를 함수처럼 호출할 수 있도록 만듭니다.
  • bool operator()(int num) → 정수 값을 받아 _value에 더한 후 변경된 값을 출력합니다.
  • functor(); → 기본 operator()가 실행됩니다.
  • functor(3);operator()(int num)이 실행되며 _value 값이 증가합니다.

2.2 함수 포인터 vs. 함수 객체

비교 항목함수 포인터함수 객체 (Functor)
시그니처 제한시그니처가 정확히 맞아야 함여러 오버로드 가능
상태 유지상태를 가질 수 없음멤버 변수로 상태 유지 가능
코드 가독성함수 사용에 유리코드 유지보수성이 좋음
활용 예제단순한 함수 호출상태를 유지하면서 동작이 필요한 경우

3. MMO 서버에서 함수 객체 활용

📌 문제 상황

MMORPG 서버에서 클라이언트가 이동 요청을 보낼 때, 모든 요청을 즉시 처리할 수는 없습니다.
따라서, 이동 요청을 큐(Queue)에 저장한 후 나중에 실행해야 합니다.

이때 Functor를 활용하면 이동 요청을 객체로 만들어 생성과 실행 시점을 분리할 수 있습니다.
이러한 패턴을 커맨드 패턴(Command Pattern) 이라고 합니다.


3.1 MMO에서의 함수 객체 활용 예제

#include <iostream>
using namespace std;

class MoveTask
{
public:
    // () 연산자 오버로딩 -> 이동 요청을 실행하는 기능
    void operator()()
    {
        cout << "플레이어 " << _playerId << "을(를) 좌표 (" << _posX << ", " << _posY << ")로 이동" << endl;
    }

public:
    int _playerId;
    int _posX;
    int _posY;
};

int main()
{
    MoveTask task;  // 이동 요청 객체 생성

    // 이동할 플레이어 ID 및 좌표 설정
    task._playerId = 100;
    task._posX = 5;
    task._posY = 5;

    // 이후 적절한 타이밍에 이동 실행
    task();  // () 연산자 오버로딩을 통해 실행 가능

    return 0;
}

📌 코드 설명

  • MoveTask 클래스는 _playerId, _posX, _posY 정보를 저장하고 있습니다.
  • operator()()를 오버로딩하여 이동 요청을 실행하는 함수처럼 동작하도록 만들었습니다.
  • task();를 실행하면 플레이어 이동이 실행됩니다.

4. 정리

기능함수 포인터함수 객체(Functor)
동작 방식함수 주소를 저장하여 실행객체를 함수처럼 호출
상태 유지 가능 여부불가능가능 (멤버 변수 이용)
코드 가독성비교적 단순유연하고 유지보수 용이
시그니처 제한반드시 일치해야 함다양한 시그니처 지원 가능
활용 예제단순한 콜백, 이벤트 핸들러비동기 작업, 상태를 유지해야 하는 동작

profile
李家네_공부방

0개의 댓글