요즘엔 이래저래 혼란이라 포스팅을 안하고 있었으나--a
개념파악은 다 한거 같고,
책 찾아 보기 귀찮은 것들만 빠르게 포스팅 하고,
API로 넘어가야 할것 같다.
새벽2 시쯤엔 잘 수 있겠지 머 -_ -;;
잡소린 그만하고,
함수 객체를 사용하는 방법은 여러가지고 존재한다.
1. 전역 함수
2. 클래스 내의 맴버 함수
3. 글래스의 연산자 오버로딩 사용
예제
1. 전역 함수
#include <iostream>
#include <vector>
#include <algorithm>
// 컨테이너 생성
std::vector< int > coll;
// 전역으로 사용할 함수 객체
void print( int& _n )
{
// 출력
std::cout << _n << std::endl;
}
void main()
{
coll.push_back( 10 );
coll.push_back( 11 );
coll.push_back( 12 );
coll.push_back( 13 );
coll.push_back( 14 );
// for_each를 사용해서 함수 객체를 사용
for_each( coll.begin(), coll.end(), print );
}
// 결과
// 10
// 11
// 12
// 13
// 14
2. 클래스 내의 맴버 함수
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
// 클래스
class AAA
{
int a;
public:
AAA( int _a ) : a(_a){}
// 클래스내에 존재하는 함수 객체
void print() // 주의 점은 추가적인 인자를 받지 않는다.
{
std::cout << a << std::endl;
}
};
void main()
{
std::vector< AAA > coll;
coll.push_back( AAA(10) );
coll.push_back( AAA(11) );
coll.push_back( AAA(12) );
coll.push_back( AAA(13) );
coll.push_back( AAA(14) );
// for_each를 사용해서 함수 객체를 사용
for_each( coll.begin(), coll.end(),
std::mem_fun_ref( &AAA::print ) ); // mem_fun_ref 를 사용해야 한다.
// 추가적으로 주의할 점은 AAA를 &로 보내주고
// 그 대상의 print를 사용하는 것이다.
// 전역처럼 1개의 함수를 사용해서 출력하는게 아니라
// 본인이 가지고 있는 함수를 불러 온다는 것이다!!!
}
// 결과
// 10
// 11
// 12
// 13
// 14
2.2 클래스 내의 인자를 추가적으로 받는 맴버 함수
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <string>
// 클래스
class AAA
{
int a;
public:
AAA( int _a ) : a(_a){}
// 클래스내에 존재하는 함수 객체
void print( std::string str ) // bind2nd를 사용하여 인자를 받을 수 있다.
{
std::cout << str << a << std::endl;
}
};
void main()
{
std::vector< AAA > coll;
coll.push_back( AAA(10) );
coll.push_back( AAA(11) );
coll.push_back( AAA(12) );
coll.push_back( AAA(13) );
coll.push_back( AAA(14) );
// for_each를 사용해서 함수 객체를 사용
for_each( coll.begin(), coll.end(),
bind2nd(
std::mem_fun_ref( &AAA::print ),
"Print : " // string을 print의 인자로 보내준다.
) );
}
// 결과
// Print : 10
// Print : 11
// Print : 12
// Print : 13
// Print : 14
3. 클래스 내의 연산자 오버로딩
#include <iostream>
#include <vector>
#include <algorithm>
// 클래스
class AAA
{
public:
int a;
AAA()
{
a = 0;
std::cout << "생성자 들림" << std::endl;
}
AAA( const AAA& _aaa )
{
std::cout << "복사 생성자를 들림" << std::endl;
a = _aaa.a;
}
// 외부에서 접근하게 될 () 연산자 오버로딩
void operator() ( int _a )
{
a += _a;
std::cout << a << std::endl;
}
};
void main()
{
std::vector< int > coll;
coll.push_back( 1 );
coll.push_back( 2 );
coll.push_back( 3 );
coll.push_back( 4 );
coll.push_back( 5 );
// for_each를 사용해서 함수 객체를 사용
AAA a = for_each( coll.begin(), coll.end(), AAA() );
// AAA()의 최종 값이 return AAA a에 담고 있다.
std::cout << a.a << std::endl;
}
// 결과
// 생성자 들림
// 1
// 3
// 6
// 10
// 15
// 복사 생성자를 들림
// 15
AAA a = for_each( coll.begin(), coll.end(), AAA() );
이 부분에 대해서 모호할 수 있는데,
AAA를 임시 객체로 생성하고 ()를 호출,
당연히 ()에 들어 가는 값은 vector의 값이고(이 예제에서는 int형)
for_each의 모든 동작이 끝나면 AAA() 임시 객체를 return,
AAA a가 그 값을 복사 생성자로 받게 된다는 것을 결과를 통해 알 수 있다.
3.2 클래스내에 존재하는 연산자 오버로딩
비슷 하지만 조금 다른 경우도 있다.
#include <iostream>
#include <vector>
#include <algorithm>
// 클래스
class AAA
{
public:
int a;
AAA()
{
a = 0;
std::cout << "생성자 들림" << std::endl;
}
AAA( int n ) : a(n){}
AAA( const AAA& _aaa )
{
std::cout << "복사 생성자를 들림" << std::endl;
a = _aaa.a;
}
// 외부에서 접근하게 될 () 연산자 오버로딩
void operator() ( AAA& _aaa )
{
a += _aaa.a;
std::cout << a << std::endl;
}
};
void main()
{
std::vector< AAA > coll;
coll.push_back( AAA(1) );
coll.push_back( AAA(2) );
coll.push_back( AAA(3) );
coll.push_back( AAA(4) );
coll.push_back( AAA(5) );
// for_each를 사용해서 함수 객체를 사용
AAA a = for_each( coll.begin(), coll.end(), AAA() );
// AAA()의 최종 값이 return AAA a에 담고 있다.
std::cout << a.a << std::endl;
}
// 결과
// 복사 생성자 들림 X 15
// 생성자 들림
// 1
// 3
// 6
// 10
// 15
// 복사 생성자를 들림
// 15
이 결과를 보면 복사생성자를 무려 15번이나 들린다는 것을 알 수 있다.
하지만 이것은 coll에 임시객체를 생성해서 값을 저장하고 있는 것이기 때문에 들르는 것이고,
왜 그 횟수가 15번인지까지는 솔직히 잘 모르겠다.
push_back를 한번만 하면 1번 밖에 안들르고,
2번째에 2번 더 들리고,
3번째에 6번 들리게 되던데,,,, 흐음..
어째뜬 그것만 제외한다면, 이전과 비슷하지만,
단지 vector가 가지는 값이 int가 아니라 AAA클래스 객체 라는 것만 빼면,
크게 차이점은 없다.
상황에 따라서 AAA 객체를 vector에 저장해야 하는 상황에서,
operator()를 int가 아닌 AAA& 로 받고 있다는 것을 주의해서 보아야 할 것이다.
함수 객체라는 기능이 매우 뛰어나다고 생각하지만,
잘 쓰지 못한다면 오히려 그것은 독이 될 수 있다고 생각한다.
아직 많이 부족하지만 당분간은 함수 객체를 어떻게 해서든 자주 사용해가는 방향으로 코딩을 해볼까 한다.
물론 operator연산도 마찬가지로,,,,
'프로그래밍 > STL' 카테고리의 다른 글
algorithm (0) | 2010.04.08 |
---|---|
연관 컨테이너 - Set, Map, multiSet, multiMap (0) | 2010.04.08 |
iterator - 반복자 (0) | 2010.04.08 |
시퀀스 컨테이너 - vector, list, deque (0) | 2010.04.05 |
용어적 설명. (0) | 2010.04.05 |