ㅇ 함수 객체
STL의 알고리즘들은 전역 함수가 처리하며 문제를 풀기 위한 반복자 구간, 검색 대상, 채울 값 따위의 정보들이 함수의 인수로 전달된다.
알고리즘 함수들은 입력된 정보를 바탕으로 알아서 동작하지만 어떤 함수들은 내부에서 모든 동작을 다 처리하지 않거나
할수 없는 경우도 있다. 검색하고자 하는 값이 정확하게 어떤 조건인지, 정렬을 위해 요소를 어떤 방식으로 비교할 것인지를 함수가
마음대로 결정 할 수 없다.
이때 함수에게 좀더 구체적인 처리 방식을 지정하기 위해 사용자가 미리 만들어 놓은 함수 객체를 전달한다.
알고리즘 함수는 동작중에 사용자의 개입이 필요한 부분에 대해서 함수 객체를 호출하여 의사를 결정한다.
for_each 함수를 사용하면 순회를 대신 시킬 수 있으며 이때 순회 중에 어떤 작업을 할 것인가를 함수 객체로 지정한다.
for_each함수의 원형은 다음과 같다.
UniOp for_each ( InIt first, InIt last, UniOp op);
순회는 for_each가 되신 하되 순회중의 각 요소에 대한고유한 작업은 함수객체가 처리하는 방식이다.
예 제 : for_each
1 /// for_earch과함수객체에대한사용예
2 /// 예제에서는함수객체가아닌일반함수를넘겼다.
3
4 #include <iostream>
5 #include <vector>
6 #include <algorithm>
7
8 using namespace std;
9
10 void print(int _nValue)
11 {
12 printf("%d\n", _nValue);
13 }
14
15 void main()
16 {
17 int _nAri[] = { 2, 8, 5, 1, 9 };
18 vector<int>vi(&_nAri[0], &_nAri[5]);
19
20 /// 정렬
21 sort(vi.begin(), vi.end());
22
23 /// 3번째인수에함수객체가들어가야한다. 일반함수도가능
24 for_each(vi.begin(), vi.end(), print); // print : 함수 포인터
25 }
for_each 함수의 세번째 인수로 전달되는 대상을 함수객체(Function Object) 또는 펑크터(Functor)라고 하는데 예제에서는 함수 포인터로
넘겼다. 함수 포인터에만 국한 되는 것이 아니라 함수를 흉내낼 수 있는 모든 객체일 수 있다. 함수 객체(함수 호출 연산자인()를 오버로딩한객체)
를 통해 마치 함수를 호출 하듯이 객체를 호출 할 수 있다.
예 제 : functor
1 /// 함수객체에 대한 예
2 #include <iostream>
3 #include <vector>
4 #include <algorithm>
5
6 using namespace std;
7
8 /// class로선언할경우public을붙여주어야한다.
9 struct print
10 {
11 /// 함수객체선언
12 void operator()(int _nValue) const
13 {
14 printf("%d\n", _nValue);
15 }
16
17 void sum(int a)
18 {
19 printf("SUM %d \n",a);
20 }
21 };
22
23 void main()
24 {
25 int _nAri[] = { 2, 8, 5, 1, 9 };
26 vector<int> vi(&_nAri[0], &_nAri[5]);
27
28 /// print()는임시객체를생성함
29 for_each(vi.begin(), vi.end(), print());
30
31 printf("\n");
32
33 /// 임시객체를 생성하지않는방법
34 print _sPRINT;
35 sort(vi.begin(), vi.end());
36 for_each(vi.begin(), vi.end(), _sPRINT);
37 }
for_each는 반복자 순서에 맞게 순회만 할뿐이며 실제 작업은 함수 객체가 한다. 일정 구간의 요소에 대해 어떤 작업을 하고 싶다면 for_each가 가장 쉬운 방법이다.
함수 객체는 클래스안에 함수를 캡츌화해 놓은 것으로 함수 포인터에 대한 일반화라고 할 수 있다.
STL이 함수 포인터를 확장하여 함수 객체라는 더 일반화된 개념을 사용하는 이유는 포인터에 비해 몇가지 장점이 있고 더 유연하기 때문이다.
① 함수 객체는 인라인이 가능해서 처리 속도를 대폭적으로 개선할 수 있다.
② 함수 객체는 객체이기 때문에 함수 연산자() 뿐만 아니라 필요한 멤버들을 추가로 더 가질 수 있다.
예제 : functionmem
1 /// 함수객체의멤버변수이용
2 #include <iostream>
3 #include <vector>
4 #include <algorithm>
5 #include "accum.h"
6
7 using namespace std;
8
9
10 void main()
11 {
12 int ari[] = { 2, 8, 5, 1, 9 };
13 vector<int> svVI( ari[0], ari[1] );
14
15 sort( svVI.begin(), svVI.end());
16 accum sTEST;
17
18 /// for_each로전달된f는값에의한전달이기때문에원본을직접
19 /// 변경하지않기때문에값을sTEST에다시대입한다.
20 sTEST = for_each( svVI.begin(), svVI.end(), sTEST );
21
22 printf("총합= %d\n", sTEST.m_nSum);
23 }
③ 멤버 뿐만 아니라 멤버 함수도 가질 수 있으며 생성자와 파괴자도 활용할 수 있다.
생성자자는 멤버의 값을 원한는 대로 초기화 할 수 있다는 점에서 함수 객체에 대해서도 여전히 실용성이 높다.
예 제 : fuctorctor
1 /// 함수객체의생성자초기화
2 #include <iostream>
3 #include <string>
4 #include <vector>
5 #include <algorithm>
6
7 using namespace std;
8
9 struct print
10 {
11 string m_szMes;
12 print(string &_m) : m_szMes(_m) {}
13 void operator()(int a) const
14 {
15 cout << m_szMes;
16 printf("%d\n", a);
17 }
18 };
19
20 void main()
21 {
22 int ari[] = { 2, 8, 5, 1, 9 };
23 vector<int>vi(&ari[0], &ari[5]);
24
25 sort(vi.begin(), vi.end());
26
27 for_each( vi.begin(), vi.end(), print(string("요소값은")));
28 for_each( vi.begin(), vi.end(), print(string("다른메시지")));
29 }
④ 함수 객체는 타입이므로 템플릿의 인수로 사용될 수 있지만 함수 포인터는 단순한 값일 뿐이므로 템플릿의 인수로는 사용할 수 없다.
예 제 : functorpara
1 #include <iostream>
2 using namespace std;
3
4 template <typename T>
5 class SomeClass {};
6
7 struct print
8 {
9 void operator()(int a) const
10 {
11 printf("%d\n", a);
12 }
13 };
14
15
16 void func(int a)
17 {
18 printf("%d\n", a);
19 }
20
21 void main()
22 {
23 SomeClass<print> s1; // 가능
24 //someClass<func> s2; // 불가능
25 }
ps : 자세한 내용은 www.WinAPI.co.kr 참고
'[ C/ C++ 프로그래밍 ] > [ STL ]' 카테고리의 다른 글
[ 혼연 정리 ] 함수객체- 3 [미리 정의된 함수 객체] (2) | 2010.06.24 |
---|---|
[ 혼연 정리 ] 함수객체- 2 [알고리즘의 변형] (2) | 2010.06.24 |
[ 혼연 정리 ] STL 개요 - 4 [알고리즘] (1) | 2010.05.31 |
[ 혼연 정리 ] STL 개요 - 3 [ 반복자] (0) | 2010.05.31 |
[ 혼연 정리 ] STL 개요 - 2 [ STL의 구조, 컨터이너 ] (2) | 2010.05.25 |