CLOSE

Recommanded Free YOUTUBE Lecture: <% selectedImage %>

원문 : http://www.vmlinux.org/jakov/community.borland.com/15837.html

### 소개

아마도 여러분은 함수포인터(:12)를 사용해봤을 것이다. C(:12)에서 제공하는 qsort(3)와 같은 함수도 함수포인터를 사용한다. 다음은 qsort(3)을 이용해서 정렬하는 간단한 프로그램이다.
```#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int compare(const int *one, const int *two)
{
if (*one > *two)
return  -1;
else
return 1;
}

int a = { 50, 10, 20 };
int main()
{
qsort(a, 3, sizeof(a), compare);
print("%d\n", a);
return 0;
}```
qsort 함수는 인자로, 비교에 사용할 함수의 포인터를 받고 있음을 알 수 있다. 만약 함수포인터를 사용하지 않는다면, 비교연산의 종류의 갯수만큼 새로운 qsort함수를 만들어야 될 것이다.

위 코드는 일반적으로 잘 컴파일 되지만, 컴파일러의 특성에 따라서 경고를 발생하거나 컴파일이 안되는 문제가 발생할 수 있다. C 컴파일러에서 컴파일을 한다면 경고를 발생할 것이고, C++ 컴파일러에서 컴파일 한다면 에러가 발생할 것이다. 이는 이들 두개의 언어가 강타입언어이기 때문이다. C++에서 에러가 발생하는 이유는 일반적으로 C++이 더욱 강하게 타입을 검사하기 때문이다.

qsort 함수는 stdlib.h에 다음과 같이 선언되어 있다.
```void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));```

그러므로 타입을 명확히 하는 것으로 문제를 해결할 수 있다. 이제 C 컴파일러건 C++ 컴파일러건 간에 경고메시지 하나 없이 깔끔하게 컴파일 될 것이다.
`  qsort(a, 3, sizeof(a), (int (*)(const void *, const void *))compare);`

### 클래스 에서의 함수 포인터 사용

다음은 C 스타일의 함수포인터다.
```#include <iostream>

using namespace std;
void apple(void)
{
cout << "apple" << endl;
};

void berry(void)
{
cout << "berry" << endl;
}

int main()
{
void (*fptr)(void);
fptr = apple;
fptr();
fptr = berry;
fptr();
}```

위의 코드를 C++ 스타일로 바꾸어 보았다. 함수포인터를 이용해서 멤버변수에 접근함을 알 수 있다.
```#include <iostream>

using namespace std;

class fruit
{
public:
void apple()
{
cout << "apple" << endl;
}
void berry()
{
cout << "berry" << endl;
}
};

int main()
{
fruit x, *y;
void (fruit::*f)(void);

y = new fruit;
f = &fruit::apple;
(x.*f)();

f = &fruit::berry;
(y->*f)();

delete y;
}
```
C++에서의 멤버포인터를 위한 연산자를 따로 제공하다. '.*'을 사용해서 멤버함수를 포인팅할 수 있다. 호출은 '->*'를 이용하면 된다.

이제 qsort() 함수에 정렬연산을 위해서 멤버함수 포인터를 넘겨보도록 하자.
```#include <stdlib.h>
#include <iostream>

using namespace std;
class fruit
{
public:
fruit() { f = &fruit::compare; }
int (fruit::*f)(const int*, const int*);
int compare(const int *one, const int *two)
{
return ( (*one == *two) ? 0 : *one > *two );
}
} apple;

int funcptr(const void* one , const void* two)
{
return ( (apple.*apple.f)( (const int *)one, (const int *)two ) );
};

int a = { 3, 2, 1 };
int main()
{
int i;
cout << "before ";
for( i=0; i < 3; i++ ) cout << a[i] << "  ";
cout << endl;
qsort(a, 3, sizeof(a), funcptr );
cout << "after ";
for( i=0; i < 3; i++ ) cout << a[i] << "  ";
cout << endl;
return 0;
}```

### friend와 static 에서의 함수포인터 사용

이제 friend와 static 멤버함수에 접근하는 방법을 알아보자. 다음은 friend 함수에 접근하는 방법이다.
```#include <iostream>

using namespace std;

class fruit
{
public:
void apple()
{
cout << "apple" << endl;
}
void berry()
{
cout << "berry" << endl;
}
friend void cherry(void (fruit::*func)(), fruit x)
{
(x.*func)();
}
};

int main()
{
fruit x;
void (fruit::*f)(void);
f = &fruit::apple;
(x.*f)();

f = &fruit::berry;
cherry(f,x);
}```

다음은 static 멤버함수에 접근하는 방법이다.
```#include <iostream>

using namespace std;

class fruit
{
public :
void apple()
{
cout << "apple" << endl;
}
void berry()
{
cout << "berry" << endl;
}
static void cherry(void(fruit::*func)(), fruit x)
{
(x.*func)();
}
};

int main()
{
fruit x;
void (fruit::*f)(void);
f= &fruit::apple;
(x.*f)();

f = &fruit::berry;
x.cherry(f,x);
return 0;
}```

클래스에 임베디드(:12)된 함수포인터를 호출하는 방법에 대해서 알아보겠습니다. 약간더 복잡합니다.
```#include <iostream>

using namespace std;

class fruit
{
public:
void (fruit::*ff)(void);
void apple()
{
cout << "apple" << endl;
}
void berry()
{
cout << "berry" << endl;
}
};

int main()
{
fruit x;
void (fruit::*f)(void);
f = &fruit::apple;
x.ff = &fruit::berry;
(x.*f)();
(x.*x.ff)();
return 0;
}```

### 템플릿에서의 함수 포인터 사용

마지막으로 템플릿에서 함수포인터를 사용하는 방법입니다.
```#include <iostream>

using namespace std;
template<class T>
class alpha
{
T data;
public :
alpha(T x) {data = x;}
T show() {cout << data << endl;}
};

int main()
{
int (alpha<int>::*ifunc)();
float (alpha<float>::*ffunc)();
alpha<int> a(123);
alpha<float> b(456.78);

ifunc = a<int>::show;
ffunc = a<float>::show;

(a.*ifunc)();
(b.*ffunc)();

}```