정말 오랜만입니다..
이번에는 함수-객체에 대하여 간단히 정리하였습니다. 뭐, 다 그렇지만 원체 넓은 범위의 내용을 필요로 하기 때문에 간단한 사용 방법과 형태에 대하여 기록하였습니다.
처음 함수-객체의 사용 형태를 보는 사람들은 대부분 이런 형태가 생소하게 느껴질 겁니다. 함수 객체는 제네릭 알고리즘을 잘 사용하기 위해서는 절대적으로 필요합니다. 조건자(predicate)로 사용할 수 있으며, 함수 어댑터(Function Adapter)로도 사용됩니다. 이러한 내용까지 모두 거론하기엔 양이 많으니 간단하게 함수-객체가 무엇인지 한 번 보고, 간단한 예제를 보도록 하겠습니다.
C++ Standard Library에서 함수-객체에 대하여 다음과 같이 설명하고 있습니다.
함수-객체는 완전 추상화와 제네릭 프로그래밍 예이다. 함수처럼 행동하는 모든 것을 함수라고 말할 수 있다. 따라서 함수처럼 행동하는 객체를 정의한다면 이것을 함수처럼 사용할 수 있다.
함수-객체는 () 연산자를 정의한 객체이다.
FunctionObjectType fo;
...
fo(...);
fo()의 코드는 함수 fo()를 호출하는 것이 아니라 함수-객체인 fo의 () 연산자를 호출한다.
함수-객체를 처음 사용하는 사용자들은 기존의 함수에 비해서 좀 더 복잡한 방법으로 함수-객체를 정의한다고 생각할 수 있다. 즉, 다음과 같이 함수 구문 안에 모든 함수에 대한 내용을 코딩하는 것이 아니라,
void fo()
{
statements
}
함수-객체 클래스의 () 연산자 안에 코딩해야만 한다.
class FunctionObjectType {
public:
void operator() (){
statements
}
};
이런 방식의 코딩은 좀 더 복잡하지만 다음과 같은 3가지 장점을 가지고 있다.
1. 함수-객체는 상태를 가질 수 있기 때문에 좀 더 영리하다고 생각할 수 있다. 즉, 사용자는 같은 함수-객체에 대해서 동시에 다른 상태를 가질 수 있다는 것이다. 이러한 점은 기존의 함수로는 불가능하였다.
2. 각각의 함수-객체는 자신의 타입을 가진다. 그러므로 사용자는 이 함수-객체의 타입을 템플릿의 인자로 제공할 수 있다. 이는 곧 다른 함수-객체를 가지는 컨테이너를 가질 수 있다는 의미이다.
3. 함수-객체는 함수 포인터 보다 빠르다.
몇 가지 예를 보면 좀 더 이 글에 대한 이해가 쉬울 것 같습니다.
컨테이너의 모든 원소에 특정한 값을 더하는 기능을 만든다고 하면 일반적인 함수나 템플릿 함수로 할 수 있습니다.
아래 내용은 list를 double type으로 선언하고, 각 요소들의 값에 5를 더합니다.
1 /*--------------------------------------------------------------- 2 File name : function_object.cpp 3 Creater : Jeong-il Ahn(raon_pgm@naver.com) 4 Date : 2005. 02. 11. 5 Subject : Function Object 6 Purpose : 함수-객체에 대하여 이해 7 Update Date : 2005. 02. 11. 8 Version : 1.00.00 9 ----------------------------------------------------------------*/ 10 11 #include <iostream> 12 #include <cstdlib> 13 #include <algorithm> 14 #include <list> 15 16 // Print Container Element 17 template <typename T> inline void DataPrint (const T& coll, const char* str="") 18 { 19 typename T::const_iterator pos; 20 std::cout << str; 21 for (pos=coll.begin(); pos!=coll.end(); ++pos) 22 std::cout << *pos << ' '; 23 std::cout << std::endl; 24 } 25 26 // Template function 27 template <typename T> 28 void ValueAdd(T & e) 29 { 30 e += 5; 31 } 32 33 int main(int argc, char **argv) 34 { 35 using namespace std; 36 list<double> nList; 37 38 for( int i = 0 ; i < 10 ; ++i ) 39 nList.push_back(i+0.1); 40 41 DataPrint (nList, "Befor adding each element : "); 42 for_each (nList.begin(), nList.end(), ValueAdd<double>); 43 DataPrint (nList, "After adding each element : "); 44 45 return EXIT_SUCCESS; 46 } |
result
$ function_object1
Befor adding each element : 0.1 1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1
After adding each element : 5.1 6.1 7.1 8.1 9.1 10.1 11.1 12.1 13.1 14.1
하지만 컴파일 타임이 아닌 런타임에 이 값을 변경하고 싶다면 위의 방식으로는 불가능합니다. 함수가 불려지기 전에 이 함수에 값을 전달해야 하는데 이렇게 하려면 하나의 함수로는 불가능합니다. 그리고 상태를 보존하려면 static 변수를 사용하거나 같은 함수지만 다른 상태를 가져야 하는 일이 생깁니다.
아래 예는 Template 함수-객체를 선언하여 입력되는 자료 형에 맞춰 컨테이너 요소의 각 값에 입력 값을 더합니다.
1 /*--------------------------------------------------------------- 2 File name : function_object2.cpp 3 Creater : Jeong-il Ahn(raon_pgm@naver.com) 4 Date : 2005. 02. 11. 5 Subject : Function Object 6 Purpose : 함수-객체에 대하여 이해 7 Update Date : 2005. 02. 11. 8 Version : 1.00.00 9 ----------------------------------------------------------------*/ 10 11 #include <iostream> 12 #include <cstdlib> 13 #include <algorithm> 14 #include <list> 15 16 // Print Container Element 17 template <typename T> inline void DataPrint (const T& coll, const char* str="") 18 { 19 typename T::const_iterator pos; 20 std::cout << str; 21 for (pos=coll.begin(); pos!=coll.end(); ++pos) 22 std::cout << *pos << ' '; 23 std::cout << std::endl; 24 } 25 26 // Template function object 27 template <typename T> 28 class ValueAdd 29 { 30 private: 31 T value; 32 public: 33 //초기값을 갖는 생성자 34 ValueAdd(const T &v) : value(v){} 35 //()를 overloading하여 각 원소에 value를 더함 36 void operator() (T & elem) const { 37 elem += value; 38 } 39 }; 40 41 int main(int argc, char **argv) 42 { 43 using namespace std; 44 list<double> nList; 45 46 double dblInvalue = 0.; 47 cout << "Enter the number (floating type) : "; 48 cin >> dblInvalue; 49 50 for( int i = 0 ; i < 10 ; ++i ) 51 nList.push_back(i); 52 53 DataPrint (nList, "Befor adding each element : "); 54 // 각 원소에 입력된 값을 더함. 55 for_each (nList.begin(), nList.end(), ValueAdd<double>(dblInvalue)); 56 57 DataPrint (nList, "After adding each element : "); 58 59 return EXIT_SUCCESS; 60 } |
result
$ function_object2
Enter the number (floating type) : 3.25
Befor adding each element : 0 1 2 3 4 5 6 7 8 9
After adding each element : 3.25 4.25 5.25 6.25 7.25 8.25 9.25 10.25 11.25 12.25
함수-객체의 응용 범위는 상당히 넓습니다. 위의 예는 극히 간단히 형태 입니다.
미리 정의된 함수-객체가 있습니다. <functional>에 정의되어 있는데 아래 사이트를 참고하시기 바랍니다.
http://www.dinkumware.com/manuals/reader.aspx?b=p/&h=functio2.html
'C C++ - STL' 카테고리의 다른 글
STL - 13 allocator (0) | 2014.02.13 |
---|---|
STL - 12 auto_ptr (0) | 2014.02.13 |
STL - 10 Vector Container 구현 (0) | 2014.02.13 |
STL - 9 find, find_if (0) | 2014.02.13 |
STL - 8 Vector 라이브러리 (0) | 2014.02.13 |