함수 포인터는 함수를 가리키는 포인터입니다.
일반적인 포인터가 변수의 주소를 저장하는 것처럼, 함수 포인터는 함수의 주소를 저장하고 이를 호출할 수 있습니다.
#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 함수를 호출합니다.void HelloNumber(int number)
{
cout << "Hello Number: " << number << endl;
}
HelloWorld()는 매개변수가 없고 HelloNumber(int)는 int를 받으므로, HelloWorld를 가리키던 pfunc에 HelloNumber를 할당할 수 없습니다.함수 객체(Functor)란 함수처럼 동작하는 객체를 의미합니다.
이는 연산자 오버로딩을 통해 객체를 함수처럼 호출할 수 있도록 만듭니다.
#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 값이 증가합니다.| 비교 항목 | 함수 포인터 | 함수 객체 (Functor) |
|---|---|---|
| 시그니처 제한 | 시그니처가 정확히 맞아야 함 | 여러 오버로드 가능 |
| 상태 유지 | 상태를 가질 수 없음 | 멤버 변수로 상태 유지 가능 |
| 코드 가독성 | 함수 사용에 유리 | 코드 유지보수성이 좋음 |
| 활용 예제 | 단순한 함수 호출 | 상태를 유지하면서 동작이 필요한 경우 |
MMORPG 서버에서 클라이언트가 이동 요청을 보낼 때, 모든 요청을 즉시 처리할 수는 없습니다.
따라서, 이동 요청을 큐(Queue)에 저장한 후 나중에 실행해야 합니다.
이때 Functor를 활용하면 이동 요청을 객체로 만들어 생성과 실행 시점을 분리할 수 있습니다.
이러한 패턴을 커맨드 패턴(Command Pattern) 이라고 합니다.
#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();를 실행하면 플레이어 이동이 실행됩니다.| 기능 | 함수 포인터 | 함수 객체(Functor) |
|---|---|---|
| 동작 방식 | 함수 주소를 저장하여 실행 | 객체를 함수처럼 호출 |
| 상태 유지 가능 여부 | 불가능 | 가능 (멤버 변수 이용) |
| 코드 가독성 | 비교적 단순 | 유연하고 유지보수 용이 |
| 시그니처 제한 | 반드시 일치해야 함 | 다양한 시그니처 지원 가능 |
| 활용 예제 | 단순한 콜백, 이벤트 핸들러 | 비동기 작업, 상태를 유지해야 하는 동작 |