함수 객체
함수 객체 (Function Object)
함수 객체는 함수처럼 동작하는 객체
함수처럼 동적하려면 객체가 ()연산자를 정의해야 하며, ()연산자 오버로딩한 객체
함수자(Functor, Function operator)라 불리기도 한다.
장점>
다른 멤버 변수와 멤버 함수를 가질 수 있다.
일반 함수에서 하지 못하는 지원을 받을 수 있다.
함수 객체의 서명이 같아도 객체 타입이 다르면 서로 다른 타입으로 인식 (오버라이딩)
일반 함수보다 속도 빠르다.
함수 주소를 전달하여 콜백(서버에서 클라이언트 함수호출)하는 경우 이 함수 포인터는 인라인될 수 없지만(함수 포인터는 함수가 있어야 하므로 인라인 함수의 복사본 함수를 만들어 낸다) 함수 객체는 인라인될 수 있다.
컴파일러가 쉡게 최적화할 수 있다.
아래 코드 15행 처럼 functor() 함수호출하는 것처럼 보이는데, Functor 객체의 () 연산자를 호출한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 |
void Print() {
cout << "전역함수" << endl;
}
struct Functor {
void operator() () {
cout << "함수객체" << endl;
}
};
int main()
{
Functor functor;
Print();
functor(); // functor.operator()(); 와 같음
_gettch();
return 0;
} |
cs |
<실행>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 |
void Print() {
cout << "전역함수" << endl;
}
struct Functor {
void operator()() {
cout << "함수객체" << endl;
}
void operator() (int a, int b) {
cout << "함수객체" << a << ", " << b << endl;
}
};
int main()
{
Functor functor;
Print();
functor();
functor(10, 20); // functor.operator()(10, 20); 와 같음
_gettch();
return 0;
} |
cs |
<실행>
멤버 변수를 갖는 함수 객체
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 |
class Addr {
int total;
public:
explicit Addr(int n = 0) : total(n) {}
int operator()(int n) { return total += n; }
};
int main()
{
Addr add(0);
cout << add(10) << endl;
cout << add(20) << endl;
cout << add(30) << endl;
_gettch();
return 0;
} |
cs |
<실행>
함수 객체를 사용한 콜백 함수구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 |
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
struct Funcor1 {
void operator()(int n) { cout << n << endl; }
};
struct Funcor2 {
void operator()(int n) { cout << n*n << endl; }
};
struct Funcor3 {
void operator()(int n) { cout << "정수 : " << n << endl; }
};
int main()
{
int arr[5] = { 10, 20, 30, 40, 50 };
for_each (arr, arr + 5, Funcor1());
cout << endl << endl;
for_each(arr, arr + 5, Funcor2());
cout << endl << endl;
for_each(arr, arr + 5, Funcor3());
_gettch();
return 0;
} |
cs |
<실행>
for_each() 의 세번째 인수가 함수가 아닌 함수 객체를 전달한다. 또한 전달하는 객체의 타입이 모두 다른데, 이는 템플릿이라 가능하다.
함수 객체 구현
(Less 구현)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 |
bool Pred_less(int a, int b) { return a < b; }
struct Less {
bool operator()(int a, int b) { return a < b; }
};
int main()
{
Less l;
cout << Pred_less(10, 20) << endl;
cout << Pred_less(20, 10) << endl;
cout << endl;
cout << l(10, 20) << endl;
cout << l(20, 10) << endl;
cout << Less()(10, 20) << endl;
cout << Less()(20, 10) << endl;
cout << endl;
cout << l.operator()(10, 20) << endl;
cout << l.operator()(20, 10) << endl;
_gettch();
return 0;
} |
cs |
<실행>
(STL Less함수객체 사용) - le
STL 에서 지원하는 less 템플릿을 이용한 코드로, #include <functional> 이 필요하다.
typedef less<int> 는 functional 에서 지원하며, 10행 처럼 간단하게 사용하기 위해 6행에서 타입 재정의를 하였다.
코드와 실행결과로 보아 위 코드와 큰 차이가 없어 funtional 에서 위 코드처럼 구현이 된듯하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 |
#include "stdafx.h"
#include <iostream>
#include <functional> // less 템플릿 사용시 필요
using namespace std;
typedef less<int> Less; // 간단하고 쉽게 사용하고자 함.
int main()
{
Less l; // less<int> l;
cout << l(10, 20) << endl;
cout << l(20, 10) << endl;
cout << l.operator()(10, 20) << endl;
cout << endl;
cout << Less()(10, 20) << endl;
cout << Less()(20, 10) << endl;
cout << l.operator()(10, 20) << endl;
_gettch();
return 0;
} |
cs |
<실행>
(STL greater 함구 객체)
12, 13행은 Greater 객체를 만들어 사용한것이고, 15, 16은 STL greater<typename> 을 사용한것으로 결과 값이 같아 greater<typename> 은 Greater 객체처럼 구현되어 있을듯 하다.
아래 코드에서 보듯, Greater 객체는 자룔형마다 각각 정의해줘야 하나, greater 처럼 템플릿을 사용하면 한번만 정의해줘도 17행처럼 double형에도 사용 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 |
#include <iostream>
#include <functional> // greater 템플릿 사용시 필요
using namespace std;
struct Greater {
bool operator()(int a, int b) { return a > b; }
};
int main()
{
cout << Greater()(10, 20) << endl;
cout << Greater()(20, 10) << endl;
cout << endl;
cout << greater<int>()(10, 20) << endl;
cout << greater<int>()(20, 10) << endl;
cout << greater<double>()(10.1, 20.1) << endl;
_gettch();
return 0;
} |
cs |
<실행>
(STL plus, minus 함수객체)
1
2
3
4
5
6
7
8
9
10
11 |
#include <iostream>
#include <functional> // plus<> minus<>용
using namespace std;
int main()
{
cout << plus<int>()(10, 20) << endl;
cout << minus<int>()(10, 20) << endl;
_gettch();
return 0;
} |
cs |
<실행>