1. 함수 객체(Function Object)
이번에는 함수 객체(Function Object)에 대해 알아보도록 하겠습니다. 함수 포인터에 이어 함수 객체는 어떠한 기능일까요? 쉽게 말하자면, 함수 객체는 객체가 함수처럼 동작한다 하여 함수 객체라고 할 수 있는데 우리가 전에 배웠던 연산자 오버로딩에서 ()라는 연산자를 오버로딩하여 객체를 함수처럼 쓸 수 있습니다. 우선은 함수 객체를 알아보기 전에, 간단히 () 연산자에 대해 짚고 넘어가도록 하겠습니다.
우리가 살펴볼 () 연산자는 함수 호출 연산자라고 불리며, 위에서 말했듯이 이 연산자를 오버로딩하게 되면 그 객체는 함수 객체라고 할 수 있습니다. 함수 호출 연산자를 한번 정의하여, 함수 호출 연산자가 도대체 어떤 녀석인지를 봐보도록 할까요? 아래의 예제는 함수 호출 연산자를 오버로딩하는 예제입니다.
#include <iostream>
using namespace std;
class Plus
{
public:
int operator()(int a, int b)
{
return a + b;
}
};
int main()
{
Plus pls;
cout << "pls(10, 20): " << pls(10, 20) << endl;
return 0;
}
결과:
pls(10, 20): 30
위의 예제를 보시면, Plus 클래스에서 함수 호출 연산자를 오버로딩하여 정수형 데이터 두 개를 받을 수 있고, 받은 두 정수형 데이터를 서로 더해 반환하는 연산자가 정의되어 있습니다. 그리고 메인 함수 내에서는 객체 pls를 함수를 호출하듯, 매개변수를 넘기고 서로 더한 값을 받아 출력하고 있습니다. 아직 연산자 오버로딩을 기억하시고 계시다면, 'pls(10, 20)'과 같은 코드는 'pls.operator()(10, 20)'에서 '.operator()'가 생략된 형태임을 알고 계실겁니다.
이번에는 두개의 정수형 데이터를 받고, 두 정수형 데이터가 서로 같으면 1을 다르면 0을 반환하게끔 코드를 작성하도록 해봅시다.
#include <iostream>
using namespace std;
class Equal
{
public:
int operator()(int a, int b)
{
return a == b;
}
};
int main()
{
Equal cmp;
cout << "pls(5, 5): " << cmp(5, 5) << endl;
cout << "cmp.operator()(10, 20): " << cmp.operator()(10, 20) << endl;
cout << "Equal()(10, 10): " << Equal()(10, 10) << endl;
return 0;
}
결과:
pls(5, 5): 1
cmp.operator()(10, 20): 0
Equal()(10, 10): 1
위 예제에서 주목하셔야 할 부분은 함수 호출 연산자가 오버로딩 되었다는것도 있지만, 메인 함수 내에 Equal 객체로 어떻게 함수가 호출되고 있는지에 대해 보셔야 합니다. 첫번째 호출인 'cmp(5, 5)'는 우리가 첫 예제에서 보아왔던 코드로, 암묵적 호출이라고 합니다. 여기서 암묵적 호출은 밖으로 드러내지 않는 호출이라고 할 수 있으며, 그 아래에 있는 두번째 호출 'cmp.operator()(10, 20)'은 명시적 호출이라고 할 수 있습니다. 분명하게 드러내는 호출이라고 할 수 있는거죠. 그리고 세번째 호출인 'Equal()(10, 20)'은 임시 객체를 통한 암묵적 호출이라고 할 수 있습니다.
여기서 드는 의문점은, 왜 굳이 함수 호출 연산자를 오버로딩하여 객체를 가지고 함수처럼 사용할까요? 우리가 사용하고 있는 함수와는 달리 함수 객체를 사용하면 속성을 지닐 수 있는것이 가능하고, 함수 객체가 일반적인 함수보다 빠르기도 하며, 각각의 함수객체는 서로 다른 타입을 지닌다는 장점이 존재합니다. 아래의 예제는 함수 객체의 속성을 통해 값을 누적시켜, 총합을 출력하는 예제입니다.
#include <iostream>
using namespace std;
class MoneyBox
{
int total;
public:
MoneyBox(int _init = 0) : total(_init) { }
int operator()(int money)
{
total += money;
return total;
}
};
int main()
{
MoneyBox mb;
cout << "mb(100): " << mb(100) << endl;
cout << "mb(500): " << mb(500) << endl;
cout << "mb(2000): " << mb(2000) << endl;
return 0;
}
결과:
mb(100): 100
mb(500): 600
mb(2000): 2600
함수 객체에 정수형 데이터를 넘겨주면 그 값을 받아 누적시키고 반환하게 되며, 동작을 포현할 수 있으나 상태를 저장할 수 없는 일반 함수와는 상당히 비교가 되죠? 함수 객체를 사용하면 일반 함수보다 더 폭넓게, 유연하게 사용할 수 있습니다. 오늘은 함수 객체에 대해서 여기까지 살펴보도록 하겠고, 읽어주신 분들 모두 수고하셨습니다.
'프로그래밍 관련 > C++/STL' 카테고리의 다른 글
C++/STL 강좌 2편. 함수 객체(Function Object) (7) | 2013.08.04 |
---|---|
C++/STL 강좌 1편. 함수 포인터(Function Pointer) (6) | 2013.06.07 |
맨 마지막 예제에서요.
MoneyBox(int _init = 0):total(_init) { } 이부분 호출하는건
cout << "mb(100) : " <<mb(100) ; 여기서 한번만 호출하고
cout << "mb(500) : " <<mb(500) ;
cout << "mb(2000) : " <<mb(2000) ;
나머지 500, 2000 에선 외 호출은 안하는건가요??
궁금한 점이 있습니다.
"함수 호출 연산자를 오버로딩하여 객체를 가지고 함수처럼 사용할까요? " 파트
1. 함수 객체를 사용하면 속성을 지닐 수 있다.
함수는 처리과정이 완료되면 지역변수의 특성으로 소멸되는 점을 말씀하시는 건가요 ?
속성이란 어떤 것을 말씀하시는 건가요?
2. 함수 객체가 일반적인 함수보다 빠르다고 말씀 하셨는데 조금 더 자세한 설명 부탁드립니다.
어떤 동작원리로 인해 속도가 더 빠른지 궁금합니다.
3. 함수 객체는 서로 다른 타입을 지닌다는 장점
서로 다른 타입이란 템플릿으로 작성되었을 경우를 말씀하시는 건지요 ?
멤버 변수가 동일한데 어떻게 서로 다른 타입을 지닌다는 것인지 궁금합니다.
답변 부탁드립니다.
엉엉 날 가져요.
잘봤습니다. 이해하기 힘들었는데 도움이 많이 되었습니다
"함수 객체에 데이터를 넘겨주면 그 값을 받아 누적시키고 반환된다"라고 하셨는데, 일반 객체의 멤버 함수로 사용해도 데이터를 누적시키는 동일한 기능을 하지않나요?
함수 객체의 차이점은 임시객체로도 호출할 수 있다는 점. 이런건가요?