📌 함수 포인터 활용
고속 처리
int main(void)
{
int instructions[1024] = { 0 };
int pc = 0;
while (instructions[pc])
{
switch (instructions[pc])
{
case 1: //add
break;
case 2: //sub
break;
case 3: //mul
break;
case 4: //div
break;
default:
break;
}
pc++;
}
return 0;
}
위 코드는 instructions 배열 안에 있는 값에 따라 switch - case로 분기를 해 함수를 실행하는 구조문이다.
instructions 배열 안에 값이 1일 경우, add를 호출해 빠르게 처리할 수 있지만
만약 항목이 더 많아져서 배열안의 값이 1000일 경우 ( 물론 지금은 default로 처리 되지만 )
1000까지 비교해가면서 함수를 실행해야하기 때문에 속도가 느려진다.
이때 함수포인터 배열을 활용해 구조를 바꾸면 보다 빠르게 함수를 실행할 수 있어진다.
#include<stdio.h>
typedef struct MyParams {
int param1;
int param2;
int param3;
} MYPARAMS;
int (*g_op_list[5])(MYPARAMS*); // 함수 포인터 배열
int add(MYPARAMS* pParam)
{
return pParam->param1 + pParam->param2 + pParam->param3;
}
int sub(MYPARAMS* pParam)
{
return pParam->param1 - pParam->param2 - pParam->param3;
}
int mul(MYPARAMS* pParam)
{
return pParam->param1 * pParam->param2 * pParam->param3;
}
int div(MYPARAMS* pParam)
{
return pParam->param1 / pParam->param2 / pParam->param3;
}
void init_op_list(void)
{
g_op_list[1] = add;
g_op_list[2] = sub;
g_op_list[3] = mul;
g_op_list[4] = div;
}
int main(void)
{
init_op_list();
int instructions[1024] = { 0 };
int pc = 0;
MYPARAMS param = { 0 };
while (instructions[pc])
{
g_op_list[instructions[pc]](¶m);
pc++;
}
return 0;
}
위 처럼 switch - case 구문을 삭제하고 g_op_list 함수 포인터 배열을 활용해 직접적으로 해당 함수를 빠르게 호출해 줄 수 있다.
일반적인 함수를 저장하고, 다시 호출하는 방법은 위와 같다.
클래스에 있는 멤버 함수를 저장하고 호출할때는 어떻게 사용할까?
📌 클래스 함수 포인터 활용
정적
class Test
{
public:
Test();
~Test();
private:
void (Test::*Handler[5])(int a, int b);
public:
void Add(int a, int b);
}
클래스 안의 멤버 함수는 this 포인터를 받아야 하기 때문에 호출 방식이 일반 함수와는 다르다.
위의 Handler는 일반 함수가 아니라 Test 객체의 멤버 함수를 저장할 수 있다고 선언한다는 의미다.
Handler에 Test 클래스의 멤버함수를 저장하려면 다음과 같이 하면 된다.
packetProc[1] = &Test::int;
위와 같이 멤버 함수를 저장하고, 호출할때는
(this->*Handler[1])(a, b);
이처럼 호출하면 된다.
위 예시는 5개로 크기가 지정되어있는데, 동적으로 만드려면 어떻게 해야할까?
동적
class Test
{
public:
Test();
~Test();
private:
void (Test::**Handler)(int a, int b);
public:
void Add(int a, int b);
}
동적 할당 받기
Handler = new void(Test::**)(int, int)[count];
memset(Handler, 0, sizeof(void (Test::**)(int, int)) * count);
소멸자에서 해제
Test::~Test()
{
delete[] Handler;
Handler = nullptr
}
멤버함수를 저장하고, 호출하는 방식은 정적 방식과 동일하다.