네트워크 관련 프로그래밍을 짬짬히 짜보다가
if문 대신에 함수 포인터를 쓸일이 있어서 이것저것 찾아보면서 만져봤는데요, (thanks google! '▽ ')
함수포인터는 저에게는 이름만 알고 있었지 미지의 영역이였고 다른 많은 분들도 잘 알지 못하는 분들이 많을것 같아 이렇게 정리를 해서 올려봅니다.

1. 함수포인터란?
함수도 메모리 입니다. 함수가 있다면 메모리에 번지수를 할당하여 놓고, 호출시 그 번지수로 이동하여 동작을 하는 겁니다.
이러한 함수에도 포인터라는 것이 존재합니다.

2. 쓸일이 있는가?
다음과 같은 문법이 있다고 합시다. (시간상 함수 내용및 기타 오류에 대한 크리티컬한 문제는 부분은 검증하지 않고 바로 작성합니다. 양해를 바랍니다.)

void f1(int n) { std::cout << "Func 1 : " << n << std::endl; }
void f2(int n) { std::cout << "Func 2 : " << n << std::endl; }

main(void)
{
   cin >> n ;
   switch(n)
   {
     case 1:
     f1(n);
     break;

     case 2:
     f2(n);
     break;
    }
}

숫자를 입력받아 1이면 f1()함수를 2이면 f2()함수를 호출하는 간단한 내용입니다.
함수포인터를 받으면 이렇게 사용이 가능합니다.

void f1(int n) { std::cout << "Func 1 : " << n << std::endl; }
void f2(int n) { std::cout << "Func 2 : " << n << std::endl; }

main(void)
{
   void (*func_ptr[2]) (int); // 2개의 배열의 func_ptr의 이름을 가지는 함수 포인터를 사용
   func_ptr[0] = f1;            // 0번째 배열에 f1을
   func_ptr[1] = f2;            // 1번째 배열에 f2를 넣는다

   std::cin >> n ;
   (*(func_ptr[n-1]))(n);
}

약간은 쓰는 방법이 복잡해 보일지는 모르지만, 위의 첫 함수와 같은 결과를 보여주며(다시 얘기하지만 입력된 값의 신뢰문제는 고려하지 않고 얘기합니다)
이 방식은 포인트 메모리를 더 사용할지는 모르지만, if의 사용을 한단계 줄여주면서 좀더 빠른 동작을 기대할수 있게 됩니다.

클래스안에서 사용할 경우는 약간 더 복잡해지는데요, 보통 일반 함수가 cdecl 호출 방식이지만 클래스 함수들은 static를 쓰지 않는 이상 thiscall 방식이기 때문입니다.
클래스 맴버 변수를 클래스 내에서 사용하고자 하면 다음과 같이 쓰면 thiscall의 함수 포인터를 사용할수 있습니다.
class base
{
private:
   void (base::*m_pFunc[2]) (int);
public:
   base();   // 생성자
   void f1(int n)  { std::cout << "base class func 1 : " << n << std::endl; }
   void f2(int n)  { std::cout << "base class func 2 : " << n << std::endl; }
   void Print(int n) { (this->*m_pFunc[n-1])(n); }
};

base::base()
{
   m_pFunc[0] = f1;
   m_pFunc[1] = f2;
}

main(void)
{
   base B1;
   std::cin >> n;
   B1.Print(n);
}

복잡해 보여도 따지고 보면 간단한 예시이니 금방 이해하실수 있으실 겁니다.
중요한건 base::* 형으로 소속을 명확히 해준다는 것이구요..
더 잼있는 사실은 이것을 상속으로도 쓸수 있다는 사실이죠!! 오늘의 제일 큰 수확은 이거였습니다.

class base
{
protected:
   typedef void (base::*BASE_FUNC) (int);    // BASE_FUNC라는 이름으로 함수포인터의 타입으로 선언해주는 겁니다. 타입 선언이 독특하죠.
   BASE_FUNC m_pFunc[2];
public:
   base();   // 생성자
   void f1(int n)  { std::cout << "base class func 1 : " << n << std::endl; }
   void f2(int n)  { std::cout << "base class func 2 : " << n << std::endl; }
   virtual void Print(int n) { (this->*m_pFunc[n-1])(n); }
};

base::base()
{
   m_pFunc[0] = f1;
   m_pFunc[1] = f2;
}

class child : public base
{
public:
   child();
   void f3(int n) { std::cout << "child class func 3 : " << n << std::endl; }
   void f4(int n) { std::cout << "child class func 4 : " << n << std::endl; }
};

child::child()
{
    m_pFunc[0] = (BASE_FUNC) f3;    // 부모 클래스의 형으로 변환시킨다.
    m_pFunc[1] = (BASE_FUNC) f4;
}


main(void)
{
   child B1;
   std::cin >> n;
   B1.Print(n);
}

자세히 보시면 base 함수의 포인터 변수를 하나 잡아주고, 그것을 상속받아 자식 클래스 생성자에서 해당 포인터의 주소를 넣어주고 있습니다.
중요한건 BASE_FUNC라는 함수 포인터 타입을 미리 base 클래스에서 잡아주고, 자식 함수는 BASE_FUNC로 캐스팅해서 쓸수 있다는 점이랄까요??
이렇게 생각하시면 될듯 싶습니다.
좀더 다양한 방법의 사용은 스스로 생각하시면 될것 같구요, 이 방식의 문제점이나 정보나 의견이 있다면 알려주시면 감사드리겠습니다.