함수 포인터는 C++에서 함수의 주소를 저장할 수 있는 포인터로, 이를 통해 함수 호출을 유연하게 관리할 수 있습니다. 이번 포스트에서는 함수 포인터의 개념을 이해하기 위해 예제 코드를 한 줄씩 분석하고, 그 의미를 자세히 설명하겠습니다.
int sum(int x, int y)
{
    return x + y;
}
int sum(int x, int y) 함수: 두 정수 x와 y를 받아 그 합을 반환하는 함수입니다.void functionPointer()
{
    // int sum(int x, int y) 을 가리킬 수 있는 함수 포인터
    int (*f0)(int, int) = ∑ // 함수의 주소
    int (*f1)(int, int) = sum;  // 함수의 이름이지만 주소로 평가 되는 것을 허용
int (*f0)(int, int) = ∑: 함수 sum의 주소를 가리키는 함수 포인터 f0를 선언합니다. &sum은 sum 함수의 주소를 가져옵니다.int (*f1)(int, int) = sum;: sum 함수 이름을 사용해 함수 포인터 f1을 초기화합니다. 함수 이름 자체가 함수의 주소로 평가되므로 & 연산자를 생략할 수 있습니다.    cout << (*f0)(1, 2) << endl;
    cout << f0(1, 2) << endl;  // 역참조 생략 허용
(*f0)(1, 2): f0 포인터를 역참조하여 sum 함수를 호출합니다. 1과 2를 인수로 전달해 sum이 반환하는 결과인 3을 출력합니다.f0(1, 2): 함수 포인터를 사용할 때 역참조(*)를 생략할 수 있으므로, 동일하게 sum(1, 2)를 호출합니다.    int(&f2)(int, int) = sum; // 함수 참조
    //int (&f3)(int, int) = ∑ // 안 됨
int(&f2)(int, int) = sum;: 함수 참조 f2를 선언하고 sum 함수에 바인딩합니다. 함수 참조는 함수 포인터와 비슷하지만, 함수 이름에 직접 참조자를 사용합니다.int (&f3)(int, int) = ∑ // 안 됨: 함수 참조는 함수 포인터와 달리 주소 연산자(&)를 사용하지 않으므로 컴파일 오류가 발생합니다.    cout << f2(1, 2) << endl;
    cout << (*f2)(1, 2) << endl; // 허용
    cout << (*sum)(1, 2) << endl; // 허용, 함수 주소가 필요한 곳에서는 암시적으로 함수 주소로 변경
}
f2(1, 2): f2 참조를 통해 sum 함수를 호출합니다.(*f2)(1, 2): 함수 참조도 함수 포인터처럼 역참조하여 호출할 수 있습니다.(*sum)(1, 2): sum 함수 자체도 *sum으로 역참조할 수 있으며, 이때 암시적으로 함수 주소로 처리됩니다.enum struct RequestType
{
    Login, Register, Update, Delete
};
enum struct RequestType: 네 가지 요청 타입을 정의하는 열거형입니다. 각각 Login, Register, Update, Delete 값이 있습니다.bool onLogin(string id, string password)
{
    cout << "onLogin" << endl;
    cout << id << endl;
    cout << password << endl;
    return true;
}
bool onRegister(string id, string password)
{
    cout << "onRegister" << endl;
    cout << id << endl;
    cout << password << endl;
    return true;
}
bool onUpdate(string id, string password)
{
    cout << "onUpdate" << endl;
    cout << id << endl;
    cout << password << endl;
    return true;
}
bool onDelete(string id, string password)
{
    cout << "onDelete" << endl;
    cout << id << endl;
    cout << password << endl;
    return true;
}
onLogin, onRegister, onUpdate, onDelete 함수들: 각각 로그인, 회원가입, 업데이트, 삭제 요청을 처리하는 콜백 함수입니다. 이 함수들은 ID와 패스워드를 출력하고 true를 반환합니다.void callback()
{
    bool (*callbacks[])(string, string) {
        onLogin, onRegister, onUpdate, onDelete
    };
bool (*callbacks[])(string, string): 함수 포인터 배열 callbacks를 선언하여, onLogin, onRegister, onUpdate, onDelete 함수들의 주소를 저장합니다.    callbacks[(int)RequestType::Login]("daoid", "1234");
    callbacks[(int)RequestType::Register]("daoid", "1234");
    callbacks[(int)RequestType::Update]("daoid", "1234");
    callbacks[(int)RequestType::Delete]("daoid", "1234");
}
callbacks[(int)RequestType::Login]("daoid", "1234");: RequestType::Login의 인덱스로 callbacks 배열에서 onLogin 함수 포인터를 선택하고, "daoid"와 "1234"를 인수로 호출합니다. Register, Update, Delete에 대해서도 같은 방식으로 호출합니다.struct Character
{
    int health;
    void (*dieCallback)();
};
struct Character: 캐릭터의 health와 캐릭터가 죽을 때 호출될 함수 포인터 dieCallback을 가지는 구조체입니다.void damaged(Character& character)
{
    character.health -= 100;
    if (character.health <= 0)
    {
        cout << "died" << endl;
        if (character.dieCallback)
            character.dieCallback();
    }
}
void damaged(Character& character): 캐릭터의 health를 100만큼 감소시키고, health가 0 이하가 되면 "died"를 출력하고 dieCallback을 호출합니다.void gameOver()
{
    cout << "gameOver" << endl;
}
void playCharacter()
{
    Character character0{ 200, nullptr };
    Character character1{ 200, gameOver };
    damaged(character0);
    damaged(character0);
    damaged(character1);
    damaged(character1);
}
void gameOver(): 게임 오버 시 호출되는 함수입니다. "gameOver"를 출력합니다.playCharacter(): Character 인스턴스를 생성하고, character0은 dieCallback이 nullptr인 상태로, character1은 gameOver 함수를 콜백으로 설정하여 damaged 함수로 호출합니다.character0: 두 번의 데미지로 인해 죽지만 콜백이 설정되지 않아 아무 일도 일어나지 않습니다.character1: 두 번의 데미지 후 "died"와 "gameOver"가 출력됩니다.std::function 사용 예제void func(int num)
{
    cout << num << endl;
}
typedef float real32_0;  // float의 별칭 real32
typedef double real64_0; // double의 별칭 real64
typedef void (*FuncType_0)(int);
using real32_1 = float;  // float의 별칭 real32
using real64_1 = double; // double의 별칭 real64
using FuncType_1 = void (*)(int);
typedef 및 using 구문: real32_0과 real64_0는 float과 double에 대한 별칭입니다.FuncType_0은 void (*)(int) 타입의 함수 포인터에 대한 별칭입니다.using 키워드를 사용한 real32_1, real64_1, FuncType_1은 각각 같은 역할을 하지만, 최신 C++ 스타일입니다.void type()
{
    // 길거나 복잡한 타입에 대해 간략하게 표현할 수 있다.
    auto f0 = func;
    f0(1);
auto f0 = func;: auto
키워드를 사용해 함수 포인터 타입을 자동으로 추론하여 f0를 선언합니다. f0(1)은 func(1)을 호출합니다.
    auto& f1 = func;
    f1(2);
auto& f1 = func;: 함수 참조 f1을 선언합니다. f1(2)은 func(2)을 호출합니다.    function<void(int)> f2 = func;
    f2(3);
std::function<void(int)> f2 = func;: std::function을 사용하여 func을 포장합니다. f2(3)은 func(3)을 호출합니다.    FuncType_0 f3 = func;
    f3(4);
    FuncType_1 f4 = func;
    f4(5);
}
FuncType_0 f3 = func;: 별칭 FuncType_0을 사용해 함수 포인터를 선언합니다. f3(4)은 func(4)을 호출합니다.FuncType_1 f4 = func;: using으로 선언된 FuncType_1을 사용하여 함수 포인터를 선언합니다. f4(5)은 func(5)을 호출합니다.std::function은 함수 포인터보다 유연하며, 다양한 함수 호출을 지원하는 고급 기능입니다.typedef 및 using)을 사용하면 복잡한 함수 포인터 타입을 간단하게 표현할 수 있습니다.