C++에서는 객체를(클래스) 함수처럼 사용이 가능합니다.
설명하기에 앞서 연산자 오버라이딩 개념을 알아야 합니다.
이 함수 객체를 왜!!!! 사용하는지 알아보기에 앞서서
우선 예제를 보겠습니다.
#include <iostream>
using namespace std;
class Plus{
public:
Plus(){
num = 0;
}
int operator()(){
num++;
return num;
}
int operator()(int n){
num = ++n;
return num;
}
friend ostream& operator<<(ostream&, const Plus&);
private:
int num;
};
ostream& operator<<(ostream& os, const Plus& plus){
os << plus.num << endl;
return os;
}
int main() {
Plus plus;
int num;
num = plus(5);
cout << num << endl;
for(int i = 0; i < 5; i++)
plus();
cout << plus << endl;
return 0;
}
간단한?? 예제입니다.
33행을 보면 객체를 선언하고 있지만
35행과 40행을 보면 함수처럼 사용하는걸 볼 수 있습니다.
실행결과.
사용법은 연산자 오버라이딩을 해주는 것인데 C++의 다양한 연산자들 중 '()'도 오버라이딩이 가능합니다.
따라서 선언 방법은
int operator()()
int operator()(int n1)
int operator()(int n1, int n2)
void operator()()
void operator()(int n1)
bool operator()()
......
이 정도 예시면 대충 어떤식으로 선언해야 할지 아실거라 믿습니다.
그럼 이걸 왜 사용하는지?? 알아볼 시간입니다.
함수 객체는 함수 포인터의 단점을 보완한 것인데,
사실 함수 포인터와 함수 객체를 사용하는 근본적인 목적은 같습니다.
바로 누구나 쉽고 자기 입맛대로 유연하게 사용하기 위한 범용성과
함수 포인터 or 함수 객체를 통해 코드가 간결해 지고 바로바로 원하는 함수를 가져다 쓸 수 있는 효율성 때문입니다.
하지만 함수 포인터는 명확한 type이 없고
(즉, 함수 포인터는 return type과 매개변수만 일치 한다면 어떤 것이든 들어갈 수 있기 때문에 컴파일러 입장에서는
수 많은 함수 포인터들 중 무엇이 들어갈지 알 방도가 없다는 뜻입니다.)
return type과 매개변수가 일치하는 것들만 들어갈 수 있음으로 어찌보면 제한적입니다.
때문에 C++의 장점인 inline화를 함수 포인터를 통해선 구현이 불가능 하죠.
하지만 함수 객체는 inline화가 가능 합니다.
class 즉 객체 개념으로 들어가 버려서 컴파일러가 명확한 type을 알 수 있기 때문에 컴파일 과정에서
어떤 함수 객체가 사용될지 알 수 있다는 뜻입니다.
예시를 보도록 하죠.
#include <iostream>
using namespace std;
class Plus{
public:
Plus(){
num = 0;
}
int operator()(){
num++;
return num;
}
friend ostream& operator<<(ostream&, const Plus&);
private:
int num;
};
class Minus{
public:
Minus(){
num = 0;
}
int operator()(){
num--;
return num;
}
friend ostream& operator<<(ostream&, const Minus&);
private:
int num;
};
ostream& operator<<(ostream& os, const Plus& plus){
os << plus.num << endl;
return os;
}
ostream& operator<<(ostream& os, const Minus& minus){
os << minus.num << endl;
return os;
}
template<class T>
T choice (T op){
return op;
}
int main(void) {
Plus plus;
Minus minus;
cout << choice(plus()) << endl;
cout << choice(minus()) << endl;
return 0;
}
실행 결과
간단하게 만들긴 했는데 좀 길어졌네요......
47행을 보시면 template<> 선언으로 모든 함수 객채를 받을 수 있도록 만들었습니다.
(물론..... 모든 객체를 받는건 아닙니다. 저렇게 반환되어 원하는 값을 얻기 위해선 프로그래머가 그에 맞게 코드를 짜야겠죠??)
함수 포인터로는 불가능한 일이죠.
때문에 함수 객체들은 모두 inline화가 가능한 것입니다.
이러한 점 때문에 STL에 있는 많은 알고리즘 코드 들이 함수 객체를 이용되어 사용할 수 있도록 만들어 졌습니다.
예시를 들자면
for_each(), find_if() 등....
제가 최근에 사용해본 C++ Restful open source인 casablanca 에서도 많이 사용되고 있었습니다.
하지만 함수 객체의 단점도 분명히 존재 합니다.
inline의 단점인 실행크기가 늘어난다는 점과
코드의 길이가 너무 길어진다는 점!!
이를 개선하기 위해 나온 것이 또!! 있습니다.(양파처럼 까면 계속해서 나옵니다.... 에휴)
바로 Lambda라는 녀석입니다.~~ ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
ㅠㅠ
'프로그래밍 > C++' 카테고리의 다른 글
C++ for_each문 개념과 사용법 설명 (0) | 2019.08.01 |
---|---|
C++ 함수 포인터란? 왜 사용할까? (2) | 2019.07.20 |
C++ inline 함수란? (3) | 2019.07.13 |
C++ Lambda 사용 이유와 사용 방법 (12) | 2019.07.01 |
C++ 변수 형 타입 auto (0) | 2019.07.01 |
댓글