2012-04-15 2 views
1

그물에서 함수 개체 (호출 수신자)에 대한 몇 가지 예제를 찾았지만 콜백 함수 (호출자라고하는 호출자)의 인수로 사용하는 방법을 보여주지는 않았지만 sort 또는 for_each를 사용할 때 사용됩니다. 따라서, 내가 하나를 자신을 만든 :비 STL 함수 개체 콜백 사용

class CBase 
{ 
public: 
virtual int operator()(int a, int b) 
{ 
    return 10; 
} 
}; 

class CSmaller: public CBase 
{ 
public: 
int operator()(int a, int b) 
{ 
    return a < b; 
} 

int Compute(int a, int b) 
{ 
    return a < b; 
} 
}; 

class CLarger: public CBase 
{ 
public: 
int operator()(int a, int b) 
{ 
    return a > b; 
} 

int Compute(int a, int b) 
{ 
    return a > b; 
} 
}; 

int caller(CBase &f, int x0, int x1) 
{ 
return f(x0,x1); 
} 

int main() 
{ 
CLarger callee1; /*this callee is being called by caller*/ 
CSmaller callee2; /*idem*/ 
int q=caller(callee1,0,1); 
int z=caller(callee2,0,1); 
printf("%d\n",q); 
printf("%d\n",z); 
} 

(가 종종 일반적인 이름/클래스 '템플릿'앞에 때문에)이 방식으로 구현 (더 적은 같은) 그 STL의 함수 객체가 있습니까? 즉, (CLarger와 CSmaller)는 각각의 클래스에 대해 확장되는 가상 함수가있는 관계/공통 아케스트를 가지고 있습니까? 아니면 (두 개의 인수로() 연산자를 구현하는 한) 일반 함수 객체 일 수 있습니까? 이와 같이 (테스트되지 않은 경우) :

template<class F> 
float integrate(const F &f,float x0,float x1) 
{ 
..f(x)..; 
} 

float derive(const F &f,float x0,float x1) 
{ 
..f(x)..; 
} 

class CSquare 
{ 
public: 
float operator()(float x) 
{ 
    return x*x; 
} 
}; 

class CTwoX 
{ 
public: 
float operator()(float x) 
{ 
    return 2*x; 
} 
}; 

이것이 올바른 방법이라면, 이러한 비 관련 클래스는 비 STL 방식으로 어떻게 구현 될까요? 템플릿을 사용하고 기본 메커니즘을 유지한다는 것을 알고 있지만 (형식이 서로 관련되어 있음) 형식 만 다릅니다. 그러나 그러한 관계 (즉, 동일한 보위부)가 필요합니까?

편의상 함수 객체에 오버로드 된()을 사용하고 있습니까? CLarger 's Compute도 사용할 수 있기 때문입니다. 또한 CCompute 클래스에서 예를 들어, 크고 작은 멤버로 분리 된 클래스 (다른 기능에 대해 가상으로 사용 된)를 병합 할 수도 있습니다. BTW, 나는 클래스에서 도출하고 통합 할 수 있다고 생각합니다. 내 qeustions 이해가 되니, 내 생각은 STL 이론에 반하는가?

+0

주 : STL! = 표준 라이브러리와 일치하는 어떤 것이 든 Pred에 의존합니다. – Griwes

답변

1

상속 또는 템플릿 중 하나를 선택할 수 있습니다. 그러나 요구 사항도 아닙니다. STL 함수는 템플리트 화되어 있으므로 표현식 f(x)이 필요에 따라 작동하는 한 f (예 : 함수 포인터, 펑터 - 호출 수신자)에 대해 아무 것도 전달할 수 없습니다.

참고 : f(x)은 예제 일뿐 정확한 매개 변수 수는 사용 된 특정 STL 함수에 따라 다릅니다.

상속의 장점은 기본 동작을 기본 클래스에 캡슐화하고 런타임에 실제 유형을 기반으로 실행할 수 있다는 것입니다.

템플릿의 이점은 템플릿 매개 변수를 기반으로 모든 유형의 템플릿을 사용할 수 있다는 것입니다. 따라서 각 클래스에서 operator()을 오버로드 할 수 있지만 각 유형을 처리 할 수있는 템플릿 클래스를 만드는 것이 더 쉽습니다 템플릿을 사용하는 경우, 그것은을 위해 (각 실제 템플릿 매개 변수 유형 조합 함수의 인수를 허용

+0

문제는 stdlib 알고리즘이 펑터 _by value_를 허용하기 때문에 포인터/참조에서 기본 클래스로 펑터를 전달하려고하면 객체 분할이 발생하므로 가상 함수가 다형 적으로 동작하지 않습니다. 이러한 이유로 템플릿은 상속보다 우수합니다. – ildjarn

0

STL 알고리즘의 다른 유형을 생성하는

주 (템플릿 특수화를 사용하는 특별한 처리는 특정 유형에 필요한 경우) 예를 들어, 술어)는 일반적으로 "함수와 같은"인터페이스와 일치하는 한 인수가 어떻게 생성되는지에 상관하지 않습니다. 그것을 할 필요가 모든 그것을 다른 방법으로 (함수, 펑터를 할 구현 될 수있는 Pred 유형에 대해 너무 많은 다른 가능한 방법이 있습니다

template< typename FwdIter, typename Pred > 
FwdIter find_if(FwdIter first, FwdIter last, Pred pred); 

/* .. etc ... */ 

bool is_equal_to_one(int n) { return n == 1; } 

int main() 
{ 
    std::vector<int> foo; 
    std::vector<int>::const_iterator iter; 
    iter = std::find_if(foo.begin(), foo.end(), is_equal_to_one); 
} 

의 라인을 따라 템플릿 인수 공제와 유형을 추론이다 , std :: function ...). find_if 함수는

+0

참고 : STL! = 표준 라이브러리. – Griwes