프로그래밍/C++

함수 객체

에어버스 2018. 6. 9. 17:42

함수 객체 (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(1020); //     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*<< endl; }
};
struct Funcor3 {
    void operator()(int n) { cout << "정수 : " << n << endl; }
};
 
int main()
{
    int arr[5= { 1020304050 };
    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(1020<< endl;
    cout << Pred_less(2010<< endl;
    cout << endl;
    cout << l(1020<< endl;
    cout << l(2010<< endl;
    cout << Less()(1020<< endl;
    cout << Less()(2010<< endl;
    cout << endl;
    cout << l.operator()(1020<< endl;
    cout << l.operator()(2010<< 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(1020<< endl;
    cout << l(2010<< endl;
    cout << l.operator()(1020<< endl;
    cout << endl;
    cout << Less()(1020<< endl;
    cout << Less()(2010<< endl;
    cout << l.operator()(1020<< 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()(1020<< endl;
    cout << Greater()(2010<< endl;
    cout << endl;
    cout << greater<int>()(1020<< endl;
    cout << greater<int>()(2010<< endl;
 
    cout << greater<double>()(10.120.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>()(1020<< endl;
    cout << minus<int>()(1020<< endl;
    _gettch();
    return 0;
}
cs

<실행>