C/C++에선 일반적인 변수의 포인터와 마찬가지로 함수의 포인터를 사용 할 수 있다. 이러한 문법이 가능한 이유는 함수 또한 해당 함수 코드가 있는 메모리 공간이 있고, 함수는 이 메모리의 주소값을 가지고 호출 하는 것이기 때문에 이러한 주소값을 바탕으로 함수 포인터를 사용 할 수 있는 것이다.
함수 포인터는 일반적으로, 어떤 공통적인 로직을 지닌 함수에서 특정 조건을 체크해서 다른 동작을 하도록 구현하고 싶을때 사용한다. 예를 들어서 최대값을 구하는 함수를 구현할 때, 최대값을 체크하는 함수를 인자로 받아서 여러가지 조건에 따라서 최대값을 구할수 있도록 구현 할 수 있다.
함수 포인터는 일반적인 포인터 변수를 선언 하는 것과 같이 선언 할 수 있다.
(return type)(*function pointer name)(argments) = FunctionName or &FunctionName
// 함수 포인터 선언의 예시
bool(*fncName)(int) = IsTrue or &IsTrue // 포인터 변수에 할당 하는 것 처럼 & 기호를 붙일수도 있고, 생략할 수도 있다.
함수 포인터 또한 일반 변수 처럼 typedef를 이용해서 변수를 정의 할 수 있다. typedef는 타입을 또 다른 이름, 즉 별칭으로 선언 할 수있도록 해주는 문법이다.
typedef는 일반적인 변수의 선언의 제일 앞에 typedef를 붙이는 방법으로 구현 가능하다.
int num; // -> num 변수 선언
typedef int NUM // -> 제일 앞에 typedef를 붙임으로서 NUM이 int를 의미하는 타입이 된다.
NUM randNum = 10; // == int randNum = 10; 과 같은 의미이다.
typedef int ARR[10]; // 이런 방법으로 배열 타입도 정의가 가능하다.
ARR arr; // == int arr[10]; 과 같은 의미이다.
함수 포인터 또한 typedef를 통해 선언 할 수 있는데, 해당 방법이 일반적으로 함수 포인터를 정의하는 방법이다.
typedef int(*PFUNC)(int, int) // int를 반환하고, int 두개를 인자로 받는 함수 포인터의 타입 정의
PFUNC pFunc = &Function; // 이렇게 함수를 할당하여 사용할수있다.
int res = pFunc(10, 10); // 일반 함수와 같은 방식으로 사용
일반적인 함수 포인터는 정적 함수 혹은 전역 함수만 담을 수 있다. 왜냐하면 클래스의 멤버 변수는 하나의 객체에 종속되어 있는 형태로, 반드시 클래스 객체를 통해서만 호출 할 수 있기 때문이다. 이러한 차이점이 있는 멤버 함수를 위해 멤버 함수 포인터를 정의 할 수 있는 방법이 존재한다.
typedef int(MyClass::*MPFUNC)(int, int) // 이렇게 함수 포인터의 이름 앞에 종속 되는 클래스를 MyClass::를 통해 명시해주면 된다.
MPFUNC mpFunc = &MyClass::Function;
여기서 가장 중요한 점은 멤버 함수 포인터를 초기화 할때는 반드시 & 기호를 붙여줘야한다. 또한 호출시에도 반드시 *를 통해서 멤버 함수를 호출해 주어야 한다.
(myClass.*mpFunc)(0, 0); // 이렇게 함수 포인터 앞에 *를 붙이고, 호출하는 객체와 함께 괄호로 묶어주여야 한다.
(myClass->*mpFunc)(0, 0); // 만약 객체 포인터를 통해 호출한다면, ->를 사용하면 된다.
위와 같이 멤버 함수 포인터를 호출 할 때 반드시 기호와 함께 호출해야 하는 이유는, 를 붙이지 않으면, 컴파일러에게 해당 객체의 멤버를 호출하는지, 함수 포인터를 호출하는지를 구분해 주기 위해서이다.