함수 객체(Function Object)
는 함수처럼 동작하는 객체이다. 함수처럼 동작하려면 객체가 ( )
연산자를 정의해야 한다. 다시 말해 ( )
연산자를 오버로딩한 객체이다. 함수 객체는 함수자(Functor)
라 불리기도 한다.
#include <iostream>
using namespace std;
void Print()
{
cout << "전역 함수!" << endl;
}
struct Functor
{
void operator()()
{
cout << "함수 객체!" << endl;
}
};
int main()
{
Functor functor;
Print(); // 전역 함수 호출
functor(); // 멤버 함수 호출 functor.operator()와 같다.
return 0;
}
functor
는 객체지만 함수처럼 호출할 수 있다. ( )
연산자 멤버 함수를 호출한다. 당연한 이야기지만 매개변수 리스트를 갖는 함수 객체를 만들수 있다.
#include <iostream>
using namespace std;
void Print(int a, int b)
{
cout << "전역 함수: " << a << ',' << b << endl;
}
struct Functor
{
void operator()(int a, int b)
{
cout << "함수 객체: " << a << ',' << b << endl;
}
};
int main()
{
Functor functor;
Print(10, 20); // 전역 함수 호출
functor(10, 20); // 멤버 함수 호출 functor.operator()와 같다.
return 0;
}
functor(10, 20)
문장은 실제 functor.operator()(10, 20)
처럼 멤버 함수를 호출한다.
일반 함수
보다 복잡해 보이는 함수 객체
를 사용하는 이유가 무엇일까?
함수 객체(Functor)의 장점
함수 객체
는 함수처럼 동작하는 객체이므로 다른 멤버 변수와 멤버 함수를 가질 수 있고, 일반 함수에서 하지 못하는 지원을 받을 수 있다. 또한, 함수 객체의 섬여이 같더라도 객체 타입이 다르면 서로 전혀 다른 타입으로 인식한다.
속도도 일반 함수보다 함수 객체가 빠르다. 함수의 주소를 전달하여콜백
하는 경우 이 함수 포인터는인라인
될 수 없지만(함수 포인터
는 함수가 있어야 하므로인라인
함수의 복사본 함수를 만들어 낸다)함수 객체
는인라인
될 수 있고,컴파일러
가 쉽게최적화
할 수 있다.
다음은 함수 객체
의 장점을 보이기 위한 예제이다.
#include <iostream>
using namespace std;
class Adder
{
public:
explicit Adder(int n = 0) : total(n) {}
int operator()(int n)
{
return total += n;
}
private:
int total;
};
int main()
{
Adder add(0);
cout << add(10) << endl;
cout << add(20) << endl;
cout << add(30) << endl;
return 0;
}
/* 결과
10
30
60
*/
초깃값 0을 시작으로 add()
함수를 호출할 때마다 정수를 누적하고 반환한다. 여기서 operator()(int n)
함수는 클래스 내부에 정의되므로 암묵적으로 인라인 함수
가 된다. 또한 operator()(int n)
과 서명이 같더라도 타입이 다른 함수 객체
는 Adder 클래스 객체에 대입하거나 복사할 수 없다.
#include <algorithm>
#include <iostream>
using namespace std;
// client
struct Functor1
{
void operator()(int n)
{
cout << n << " ";
}
};
struct Functor2
{
void operator()(int n)
{
cout << n * n << " ";
}
};
struct Functor3
{
void operator()(int n)
{
cout << "정수 : " << n << endl;
}
};
int main()
{
int arr[5] = { 10, 20, 30, 40, 50 };
// 임시 함수 객체(Functor1)을 만들어 함수로 전달
for_each(arr, arr + 5, Functor1());
cout << endl << endl;
// 임시 함수 객체(Functor2)을 만들어 함수로 전달
for_each(arr, arr + 5, Functor2());
cout << endl << endl;
// 임시 함수 객체(Functor2)을 만들어 함수로 전달
for_each(arr, arr + 5, Functor3());
return 0;
}
/* 결과
10 20 30 40 50
100 400 900 1600 2500
정수 : 10
정수 : 20
정수 : 30
정수 : 40
정수 : 50
/*
STL
에는 유용하게 사용할 수 있는 함수 객체
가 내장돼 있다. 그중 대표적인 함수 객체
가 less
와 greater
이다.
less
는 <
연산자의 함수 객체이며, greater
는 >
연산자의 함수 객체이다. 또한 less
와 greater
는 bool
형을 반환하는 조건자(predicate)
이다.
다음은 두 정수를 입력받아 <
연산을 수행하는 함수와 함수 객체를 구현한 예이다.
#include <iostream>
using namespace std;
bool Pred_less(int a, int b)
{
return a < b;
}
struct Less
{
bool operator()(int a, int b)
{
return a < b;
}
};
int main()
{
Less less;
cout << Pred_less(10, 20) << endl;
cout << Pred_less(20, 10) << endl;
cout << endl;
cout << less(10, 20) << endl; // less 객체로 암묵적 함수 호출
cout << less(20, 10) << endl; // less 객체로 암묵적 함수 호출
cout << Less()(10, 20) << endl; // 임시 객체로 암묵적 함수 호출
cout << Less()(20, 10) << endl; // 임시 객체로 암묵적 함수 호출
cout << endl;
cout << less.operator()(10, 20) << endl; // less 객체로 명시적 함수 호출
cout << Less().operator()(10, 20) << endl; // 임시 객체로 명시적 함수 호출
return 0;
}
다음은 STL
의 less
함수 객체를 사용한 예이다.
#include <functional> // less<> 헤더
#include <iostream>
using namespace std;
// typedef less<int> Less;
using Less = less<int>;
int main()
{
Less less;
cout << less(10, 20) << endl; // less 객체로 암묵적 함수 호출
cout << less(20, 10) << endl; // less 객체로 암묵적 함수 호출
cout << Less()(10, 20) << endl; // 임시 객체로 암묵적 함수 호출
cout << Less()(20, 10) << endl; // 임시 객체로 암묵적 함수 호출
cout << endl;
cout << less.operator()(10, 20) << endl; // less 객체로 명시적 함수 호출
cout << Less().operator()(10, 20) << endl; // 임시 객체로 명시적 함수 호출
return 0;
}
다음은 유용하게 쓰이는 plus와 minus 함수 객체를 구현한 예이다.
#include <functional> // plus<>, minus<> 헤더
#include <iostream>
using namespace std;
struct Plus
{
int operator()(int a, int b)
{
return a + b;
}
};
struct Minus
{
int operator()(int a, int b)
{
return a - b;
}
};
int main()
{
cout << Plus()(10, 20) << endl;
cout << Plus()(20, 10) << endl;
cout << Minus()(10, 20) << endl;
cout << Minus()(20, 10) << endl;
cout << endl;
cout << plus<int>()(10, 20) << endl;
cout << plus<int>()(20, 10) << endl;
cout << minus<int>()(10, 20) << endl;
cout << minus<int>()(20, 10) << endl;
return 0;
}
/* 결과
30
30
-10
10
30
30
-10
10
*/
사용자 정의 Plus
, Minus
와 STL
의 plus
, minus
함수 객체의 결과는 같다. STL
에서 함수 객체
는 곳곳에 사용되며 중요한 역할을 한다.