c++에서 함수 포인터 사용하는 이유는??

zestys의 이미지

지금 a*알고리즘을 보고 있는데 참고하고 있는 책의 소스에서는 c++을 이용하면서 함수 포인터를 이용하더군요
(서적 : AI Game Programming Wisdom)

함수 포인터를 실제로 사용해보진 않았는데 대충 c++의 가상함수 비슷하게 동적으로 함수를 호출 할 때 사용하는걸로 알고 있습니다.

여기서는 순전히 저의 생각인데...;;;

c++에서 CAStar class와 MFC코드와 독립적으로 분리 하기위해서 사용한것 같은데 제생각이 맞는지요?

그리고 저의 짧은 지식으로는 굳이 저렇게 할 필요는 없다고 보이는데...순전히 제맘대로 생각이지만요..-_-;;

혹시 이소스 분석해 보신분의 따끔한 충고 부탁합니다..!!

혹시나해서 소스 첨부 합니다~~

File attachments: 
첨부파일 크기
Package icon ase.zip45.6 KB
winner의 이미지

생각보다 양이 많은데다가 정확히 뭐하는 program 인지 몰라서..
실행시켜보니 A* search 를 써서 시작과 끝을 연결하면서 다른 block 은 피해가는 것
같은데 뭔가 bug 가 있는 것 같기도 하고...

함수 pointer 가 source 어느 위치에서 사용되는지 알려주시면 좋겠네요.
대충 봤는데 함수 pointer 가 어디 있는지 모르겠더라고요.

그래서 순수하게 C/C++ 에서 함수 pointer 가 어떻게 쓰이는지 C++ 의 가상함수랑 어떻게 다른지만 말하겠습니다.

우선 가상함수는 C++ 에서 등장한 것이고 같은 이름의 함수 중에 동적 data type 에 맞는 함수가 호출됩니다.
같은 이름의 함수라는 점은 C 에서는 당연히 불가능한 것이고,
동적 data type 들은 class 상속구조로 연결되어 있어야 한다는 제약이 따르지만 분명히 다른 type 이죠.
좀더 정확하게 말하자면 member 함수이지만 결국 이 data type 들에 적용되는 함수들이
overriding 이라는 이름의 기법으로 같은 이름을 갖습니다.

그에 비해 C/C++ 의 함수 pointer 는 type 이 같은 여러 다른 이름의 함수들 중에
programmer 가 상황에 맞춰 선택을 하는 방식을 사용합니다.
이 경우 type 은 compile 할 때 결정되는 정적 type 이지 동적 type 은 아니지만
programmer 가 선택할 수 있다는 점은 가상함수랑 유사해 보입니다.
즉 type 이 맞기만 한다면 다른 함수들을 사용할 수 있다는 점은 동적입니다. type 은 동적이지 않지만요.

동일한 type 을 다루는 함수에 다른 value 를 넘겨주는 것이 가능하지 않습니까.
하지만 이 value 를 갖고 있는 것은 동일한 이름의 변수일 수 있습니다.
즉 type 은 정적인 변수가 갖는 값은 동적이죠.

함수도 동일한 방식이 가능하다는 것이죠.

다르지만 유사점이 있다는 것으로 풀고자 하는 문제를 어떻게 해석하느냐 혹은 어떤 형태로 design 해서
programming 을 하느냐에 따라 가상함수를 썼던 것을 함수 pointer 로 쓸 수도 있고,
함수 pointer 를 썼던 것을 가상함수로 쓸 수도 있습니다. 물론 항상 가능한 것은 아니며,
결국 둘중 하나가 더 적합할텐데 지금 사용하는 방식에 뭔가 의문점이 있다면 다른 방식을 고려해 볼 수
있다는 것입니다.

가상함수에 대해서는 이해하고 있는 것으로 보이기에 함수 pointer 에 대해 예를 들자면
잘 쓰이는 곳이 우선 message driven programming 에서의 callback 함수입니다.
Message driven Programming 의 대표적인 case 로 이 경우에 해당되는 것이 Windows API Programming 일텐데요.
각 message 를 처리하는 함수를 함수 pointer 로 programmer 가 선택합니다.
WndProc 으로 흔히 작성되는 Windows Message 처리 함수역시
Window 를 생성할 때 programmer 가 지정하게 되어있습니다.

또 한가지로 많이 알고 접하는 것으로 정렬을 들 수 있습니다.
정렬을 하다보면 내림차순으로 정렬할 필요가 생길 수도 있고, 오름차순으로 정렬할 필요가 생길 수도 있습니다.
학생을 struct 로 표현한다고 할 경우 이름을 표현하는 member 를 통해 이름순으로 정렬할 수도 있고,
성적을 표현하는 member 를 통해 성적순으로 정렬할 수도 있습니다.
Windows 탐색기에서 icon 정렬순서를 file 의 이름, 형식, 크기, 수정된 날짜로 정할 수 있다는 것을 떠올려보십시요.

이러한 경우 모두 다른 정렬함수를 작성할 필요는 없습니다.
각각의 정렬함수에서 다른 부분은 각 file 의 우선순위를 비교하는 부분뿐입니다.
이 부분만을 호환되는 함수로 작성해서 정렬함수에 함수 pointer 로 넘겨주는 방식을 취하면
원하는 바를 얻을 수 있습니다.

사실 C++ 의 가상함수는 내부적으로 함수 pointer 를 사용하고 있다고 합니다.
단 동적 type 의 호환성은 물론 동적 type 자체가 C 에는 없는 개념이었기 때문에
C++ 에서 이부분을 내부적으로만 허용하여 가상함수를 만든 것 같습니다.

마지막으로 정리해보겠습니다.
가상함수
- 처리가능한 data type : class 상속구조로 연결된 동적호환가능한 type
- 호출되는 함수선택요인 : 실행시간에서의 동적 type

함수 pointer
- 처리가능한 data type : 동일 data type
- 호출되는 함수선택요인 : programmer 가 source 에서 정한대로

비록 실행시간에서의 동적 type 은 아니지만 함수 pointer 역시 programmer 가 정해서
다른 data type 을 다루는 것이 가능하긴 한데 거기는 제가 cover 가 불가능합니다.
최근에 올라온 밑의 link 된 thread 가 적절하겠지만 C 표준에 정통해야만 이해가능한 이야기입니다.
첫 주제 글의 qsort 는 유사하게 stdlib.h 에 있습니다.
이해가능한 범위에서만 void * 를 사용하시면 함수 pointer 와 함께 다른 data type 을
다루는 것에 대해서 유용하게 사용하실 수 있을 겁니다.
http://kldp.org/node/72838

zestys의 이미지

정말 많은 도움이 되었습니다.(__)
어제 너무 늦게 글을 쓰다보니 해당 부분 코드도 명시하지 않았네요...흑흑 죄송합니다.

(asinclude.h)
typedef int(*_asFunc)(_asNode *, _asNode *, int, void *);
 
(CPathfind class)
_asFunc	 udCost;		// Called when cost value is need
_asFunc  udValid;		// Called to check validity of a coordinate
_asFunc  udNotifyChild;		// Called when child is added/checked (LinkChild)
_asFunc	 udNotifyList;		// Called when node is added to Open/Closed list
 
static int AS_Valid(_asNode *, _asNode *, int, void *);
static int AS_Cost(_asNode *, _asNode *, int, void *);
static int AS_RelativeCost(_asNode *, _asNode *, int, void *);
inline int udFunc(_asFunc, _asNode *, _asNode *, int, void *);
 
int CAStar::udFunc(_asFunc func, _asNode *param1, _asNode *param2, int data, void *cb)
{
	if (func) return func(param1, param2, data, cb);
 
	return 1;
}
.
.
.

이부분을 보면 _asFunc(...)함수와 기능이 다른걸 여러개 만들어두고 사용할 때는 udFunc(...)을 이용해서 사용하는데
c++에서 이렇게 하므로해서 이득을 취할수 있는게 있는게 있나요?

winner의 이미지

이건 MFC 같은데 전 MFC 를 조금만, 그것도 약 4년 전에 공부해봤습니다.
Windows API Programming 도 이제 걸음마할 정도만 익혔고요.

헝가리안 표기법이 제 마음을 어지럽히는군요.

이 program 의 의도는 좀 알겠네요.
생각해보면 A* 탐색이 길찾기 algorithm 이니 당연한건데... ^_^

asFunc 이라는 것은 아마도 a s(tar) 를 말하는 것일텐데
udFunc 이라는 것은 뭘 말하는 것일까요?
정말 의도를 알 수가 없습니다. u(n) d(efined) 일까요?
굳이 udFunc 이라는 것으로 감싸야했는지 전혀 이해가 안 갑니다.
아마도 debug 목적이 아니었나 싶습니다.
함수 pointer 가 제대로 설정되지 않고,
Null Pointer 라면 그대로 1을 반환하는 것을 보면 말이죠.
뭔가 program 에 이상이 있으면 1을 반환하기 전에 뭔가를 해서 알아보겠죠.
또 하나는 CASeDoc 의 SetupAStar 를 보면 m_bContinualUpdate 에 따라
udNotifyChild 에 Null Pointer 를 넣을 수 있는 부분을 보면
만일 실행된 program 의 Continual Update 가 check 되어 있지 않다면 아무 동작을 하지 않겠다는 의도겠죠.
하지만 이 code 는 틀렸을지 모릅니다. 제가 알기로 NULL 은 대부분
#define NULL ((void *)0) 으로 정의할텐데 void * 와 함수 pointer 는 호환되지 않으니까요.
앞에 쓴 글의 마지막 참조 thread 에 논의하는 것 중 하나입니다.
하지만 이 두가지 중 어느것도 굳이 udFunc 을 작성한 적절한 이유는 되지 못할 것 같습니다.

제가 생각하기에 여기서 네개의 함수 pointer 중 함수 pointer 의 의미가 살 수 있는 부분은
udCost 밖에 없을 것 같습니다. 즉 나머지는 쓸데없이 쓴 것 같습니다.
udCost 는 상대비용을 쓸지 절대비용을 쓸지를 상황에 맞춰 선택하니까요.

뭐 Windows programming 을 제대로 해보지도 못한 저이니 이쪽의 관행같은 것은
전혀 모릅니다만 정말 이해할 수 없는 source 이네요.

winner의 이미지

꼬리내리고 싶은 생각... ^_^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.