[C++]function objects

2007.05.01 02:03

단장 조회 수:1341 추천:44

카테고리 : C++     2007/01/10 16:45

STL을 아는 사람은 Function Objects를 들어보았을 것이다.



function objects가 무엇인지 외국 사이트의 내용을 번역해 올리고자 한다.  번역하는 데 나름대로 노력하겠지만



과정중에 발생하는 오역에 대해서는 책임지지 않음을 밝혀둔다.







Defining a Function Object



Function Object 작성법
By Danny Kalev





Although pointers to functions are widely used for implementing function callbacks, C++ offers a significantly superior alternative to them, namely function objects. Function objects (also called "functors") are ordinary class objects that overload the () operator. Thus, syntactically, they behave like ordinary functions.


함수 포인터가 함수callback을 구현하는데 널리 사용되지만, C++에서는 객체 함수(역자 주: function object는 함수 객체로 번역될 수 있으나 어감상 객체 함수가 더 나을 듯 하여 이 번역에서는 객체함수로 씀.)라는 월등히 우수한 대안을 제공해 주고 있다. Functor라고도 불리는 function object는 ()연산자 함수를 추가정의(역자 주: overloading: 재정의라고 할까 고민하다가 overrriding의 의미가 재정의에 맞는 것 같아 추가정의라고 번역하기로 함.)하는 보통의 클래스 객체이다.







There are several advantages in using a function object instead of a pointer to function. First, they are more resilient to design changes because the object can be modified internally without changing its external interface. A function object can also have data members that store the result of a previous call. When using ordinary functions, you need to store the result of a previous call in a global or a local static variable. However, global and local static variables have some undesirable characteristics. Finally, compilers can inline a call made through a function object, thereby enhancing performance even further. In contrast, it is nearly impossible to inline a function call made through a pointer.


함수포인터 대신 객체 함수를 쓰는 데는 몇가지 좋은 점이 있다. 먼저, 객체함수는 외부 인터페이스를 변경하지 않은체 내부구현내용을 쉽게 바꿀 수 있기 때문에 디자인 변화에 좀더 융통성이 있다. 또한 객체 함수는 앞선 호출의 결과를 저장할 수 있는 데이터멤버를 가질 수 있다. 일반 함수의 경우, 전역 변수나 지역 정적 변수를 통해서 앞선 호출의 결과를 저장해야 한다. 이 방식의 문제점은 전역변수나 지역정적변수가 몇몇 원치않는 속성들을 가지고 있다는 것이다. 마지막으로, 컴파일러는 객체 함수를 통해 이루어진 호출을 inline화 할 수 있으며 이는 performance를 훨씬 증대시킬 수 있다. 반면 포인터를 통한 함수호출은 inline화 하는 것이 거의 불가능하다.














This solution will show how to define and use a function object that implements a negation operation. The first step consists of declaring an ordinary class and overloading the () operator:


아래 코드는 음수화작업을 구현하는 객체함수를 구현, 사용하는 방법을 보여주고 있다. 첫번째 단계는 보통의 클래스를 선언하고 ()연산자 함수를 추가정의하는 것으로 이루어 진다.



  class Negate
  {
  public:
    int operator() (int n) { return -n;}
  };

The overloaded () might look a bit confusing because it has two pairs of parentheses. Remember that the first pair is always empty because it serves as the operator's name; the parameter list appears in the second pair of parentheses. Unlike other overloaded operators, whose number of parameters is fixed, the overloaded () operator may take any number of parameters.


Because the built-in negation operator is unary (it takes only a single operand), our overloaded () operator also takes a single parameter. The return type is identical to the parameter's type—int, in our example. The function body is trivial; it simply returns the negated argument.


추가정의한 ()연산자 함수를 보면 괄호가 두번이나 쓰여 조금 이상해 보일지도 모른다. 첫번째 괄호는 항상 공백이라는 것을 기억해야 하는데 이 괄호는 연산자의 이름 역할을 한다; 함수의 매개변수 리스트는 두번째 괄호안에 나타나게 된다. 여타 연산자 추가정의 함수는 매개변수의 숫자가 고정되어 있지만,  ()연산자 함수는 매개변수의 갯수에 제한이 없다. 원래 음수화함수가 하나의 매개변수만을 갖기 때문에 우리가 작성한 위 ()연산자함수도 역시 하나의 매개변수만을 갖고 있다. 리턴타입은 매개변수의 타입과 동일하며 위 예제에서는 int이다. 함수 내부는 간단하다; 그저 매개변수을 음수화하여 리턴할 뿐이다.  

















Using the Function Object



객체 함수 사용법




We now define a function named Callback() to test our function object. Callback() takes two arguments: an int and a reference to Negate. Callback() treats neg, the function object, as if it were a function's name:



이제, 객체 함수를 테스트해보기 위해 Callback()이라는 함수를 정의해 보자. Callback()함수는 두개의 매개변수를 받는다, 정수와 Negate객체에 대한 참조자. Callback()함수는 neg라는 객체함수를 마치 함수이름처럼 취급한다.




  #include "iostream"   // 편의상 꺽쇠 괄호대신 "를 사용함
  using std::cout;

  void Callback(int n, Negate & neg)
  {
    int val = neg(n);  //1번라인.  추가정의한 ()연산자함수를 호출
    cout << val;
  }

Don't let the syntax mislead you: neg is an object, not a function. The compiler transforms the line numbered 1 into the following:


문법에 속지 말자. neg는 객체이지 함수가 아니다. 컴파일러는 1번 라인을 다음과 같이 변형한다.

  int val = neg.operator()(n);

In general, function objects do not define constructors and destructors. Therefore, they do not incur any overhead during their creation and destruction. As previously noted, the compiler can inline the overloaded operator's code, thereby avoiding the runtime overhead associated with a full-blown function call.


일반적으로, 객체 함수는 생성자와 소멸자를 정의하지 않는다. 따라서, 생성, 소멸시에 부하가 걸리지 않는다. 앞선 언급했듯이, 컴파일러는 추가정의한 연산자의 코드를 inline화 할수 있으며 따라서 정상적인 함수 호출에서 발생하는 runtime부하를 피할 수 있다.

















To complete the example, we need a main() driver to pass arguments to Callback():


예제를 완성하기 위해, 우리는 Callback()함수에 매개변수값을 건제룰 main()함수가 필요하다.




   int main()
  {
   Callback(5, Negate() ); // -5 출력
  }

The program passes the integer 5 and a temporary Negate object to Callback(). As expected, the program displays -5.


위 프로그램은 정수5와 임의의 Negate객체를 Callback()함수에 건네준다. 예상처럼 -5를 출력한다.














Template Function Objects
Our example was confined to type int. However, one of the advantages of function objects is their generic nature. You can define the overloaded () operator as a member template so that it can work for any datatype: double, __int64 or char as follows:
위 예제는 int타입으로 한정되어 있지만 객체 함수의 좋은점중의 하나는 객체함수의 포괄적 속성이다.






  class GenericNegate
  {
  public:
   template  T operator() (T t) const {return -t;}
  };

  int main()
  {
   GenericNegate negate;
   cout<< negate(5.3333); // double
   cout<< negate(10000000000i64); // __int64
  }

Achieving this flexibility with ordinary callback functions is much more difficult.



이러한 융통서을 일반 콜백함수에서 구현하는 것은 엄청 어렵다.







Function Objects in the Standard Library



표준라이브러리에 포함된 객체 함수




The C++ Standard Library defines several useful function objects that can be plugged into STL algorithms. For example, the sort() algorithm takes a predicate object as its third argument. A predicate object is a templatized function object that returns a Boolean result. You can pass the predicates greater<> or less<> to sort() to force a descending or ascending sorting order, respectively:



C++ 표준라이브러리는 STL 알고리즘에 끼어넣을 수 있는 몇몇 유용한 객체함수를 정의해 놓고 있다. 예를 들어, sort()알고리즘은


세번째 변수로 predicate 객체를 받는다. predicate 객체는 템플릿 객체 함수로 boolean값을 리턴하는 객체를 말한다. greater<>나


less<>라는 predicate 객체를 sort()함수에 넣어 내림차순, 오름차순을 각각 적용할수 있다.























#include "functional"


#include "algorithm"


#include "vector"




  using namespace std;
  
  int main()
  {  
   vector  vi;
   //..객체를 채우는 작업 수행
   sort(vi.begin(), vi.end(), greater() );//descending 내림차순
   sort(vi.begin(), vi.end(), less() );  //ascending   올림차순
  }

댓글 0

파일 첨부

여기에 파일을 끌어 놓거나 파일 첨부 버튼을 클릭하세요.

파일 크기 제한 : 0MB (허용 확장자 : *.*)

0개 첨부 됨 ( / )
 
목록
번호 제목 글쓴이 날짜 조회 수
64 Guitar World선정 최고의 기타솔로곡 단장 2006.06.14 247192
63 Networking Best Practices in XBOX360 단장 2007.12.19 10893
62 마력 구하는 공식 단장 2013.07.11 7383
61 Windows 8.1 복구 파티션 만들기 단장 2013.11.13 6692
60 버텍스버퍼의 효율적인 사용 단장 2007.10.01 5100
59 효율적인 동기화를 위한 아이디어 하나 단장 2007.09.29 3279
58 vTune 사용법 단장 2009.01.13 3234
57 술의 이력서 단장 2007.02.09 2270
56 Large Address Aware file 단장 2014.03.05 1948
55 Fast Bit Counting 단장 2009.02.21 1883
54 std::tr1 단장 2008.03.13 1848
53 골프의 물리학 단장 2009.05.30 1681
52 자동차 정비용어 정리 단장 2007.01.20 1660
51 Nat기반 P2P 프로그래밍 단장 2007.11.21 1627
50 제트 추력 엔진 단장 2008.04.29 1600
49 이스람(Islam:회교:回敎)에서의 성 단장 2007.02.08 1379
48 한국운전면허를 일본운전면허로 바꾸기 [2] 단장 2007.10.26 1351
» [C++]function objects 단장 2007.05.01 1341
46 NAT 홀펀칭 단장 2007.10.25 1293
45 Stream of Life 단장 2009.06.29 1285