함수 포인터의 유용성을 보는 데 문제가 있습니다. 나는 그것이 어떤 경우에 유용 할 것이라고 생각하지만 (결국 존재한다) 함수 포인터를 사용하는 것이 더 낫거나 피할 수없는 경우를 생각할 수 없다.
함수 포인터 (C 또는 C ++)를 잘 사용하는 몇 가지 예를 들어 주시겠습니까?
답변
대부분의 예는 졸이다 콜백 : 당신은 함수를 호출 f()
하는 다른 함수의 주소를 전달 g()
하고, f()
호출 g()
일부 특정 작업에 대한합니다. 대신 f()
주소 를 전달 하면 h()
대신 f()
콜백 h()
합니다.
기본적으로 이것은 함수 를 매개 변수화 하는 방법 입니다. 동작의 일부는으로 하드 코딩되지 않고 f()
콜백 함수로 코딩됩니다 . 호출자는 f()
다른 콜백 함수를 전달 하여 다르게 행동 할 수 있습니다 . 클래식은 qsort()
C 표준 라이브러리에서 가져온 것으로, 정렬 기준을 비교 함수에 대한 포인터로 사용합니다.
C ++에서 이는 종종 함수 객체 (펑 터라 고도 함)를 사용하여 수행됩니다 . 이들은 함수 호출 연산자를 오버로드하는 객체이므로 마치 함수 인 것처럼 호출 할 수 있습니다. 예:
class functor {
public:
void operator()(int i) {std::cout << "the answer is: " << i << '\n';}
};
functor f;
f(42);
이 개념은 함수 포인터와 달리 함수 객체가 알고리즘뿐 아니라 데이터도 전달할 수 있다는 것입니다.
class functor {
public:
functor(const std::string& prompt) : prompt_(prompt) {}
void operator()(int i) {std::cout << prompt_ << i << '\n';}
private:
std::string prompt_;
};
functor f("the answer is: ");
f(42);
또 다른 장점은 함수 포인터를 통한 호출보다 함수 객체에 대한 호출을 인라인하는 것이 더 쉽다는 것입니다. 이것이 C ++에서 정렬하는 것이 때때로 C에서 정렬하는 것보다 빠른 이유입니다.
답변
글쎄, 나는 일반적으로 점프 테이블 에서 (전문적으로) 사용합니다 ( 이 StackOverflow 질문 참조 ).
점프 테이블은 유한 상태 머신 에서 일반적으로 (배타적이지는 않음) 사용되어 데이터 기반을 만듭니다. 중첩 된 스위치 / 케이스 대신
switch (state)
case A:
switch (event):
case e1: ....
case e2: ....
case B:
switch (event):
case e3: ....
case e1: ....
함수 포인터의 2d 배열을 만들고 handleEvent[state][event]
답변
예 :
- 맞춤 정렬 / 검색
- 다양한 패턴 (예 : 전략, 관찰자)
- 콜백
답변
함수 포인터의 유용성에 대한 “고전적인”예 qsort()
는 빠른 정렬을 구현하는 C 라이브러리 함수입니다. 사용자가 생각 해낼 수있는 모든 데이터 구조에 대해 보편적이되기 위해서는 정렬 가능한 데이터에 대한 두 개의 void 포인터와 이러한 데이터 구조의 두 요소를 비교하는 방법을 알고있는 함수에 대한 포인터가 필요합니다. 이를 통해 작업에 대해 선택한 기능을 생성 할 수 있으며, 실제로 런타임에 비교 기능을 선택할 수도 있습니다 (예 : 오름차순 또는 내림차순 정렬).
답변
위의 모든 사항에 동의하고 .. 런타임에 DLL을 동적으로로드 할 때 함수를 호출하기위한 함수 포인터가 필요합니다.
답변
나는 여기서 현재에 반대 할 것입니다.
C에서 함수 포인터는 사용자 정의를 구현하는 유일한 방법입니다. OO가 없기 때문입니다.
C ++에서는 동일한 결과에 대해 함수 포인터 또는 펑터 (함수 객체)를 사용할 수 있습니다.
펑 터는 객체 특성으로 인해 원시 함수 포인터에 비해 다음과 같은 여러 장점이 있습니다.
- 그들은 몇 가지 과부하를 나타낼 수 있습니다.
operator()
- 기존 변수에 대한 상태 / 참조를 가질 수 있습니다.
- 즉석에서 만들 수 있습니다 (
lambda
및bind
).
저는 개인적으로 함수 포인터보다 함수 포인터를 선호합니다 (상용구 코드에도 불구하고), 주로 함수 포인터 구문이 쉽게 어려울 수 있기 때문입니다 ( Function Pointer Tutorial에서 ).
typedef float(*pt2Func)(float, float);
// defines a symbol pt2Func, pointer to a (float, float) -> float function
typedef int (TMyClass::*pt2Member)(float, char, char);
// defines a symbol pt2Member, pointer to a (float, char, char) -> int function
// belonging to the class TMyClass
펑터가 사용할 수없는 곳에서 함수 포인터가 사용되는 것을 본 것은 Boost.Spirit뿐이었습니다. 그들은 임의의 수의 매개 변수를 단일 템플릿 매개 변수로 전달하기 위해 구문을 완전히 남용했습니다.
typedef SpecialClass<float(float,float)> class_type;
그러나 가변 템플릿과 람다가 모퉁이에 있기 때문에 우리가 오랫동안 순수한 C ++ 코드에서 함수 포인터를 사용할지 확신 할 수 없습니다.
답변
C에서 고전적인 용도는 qsort 함수입니다 . 여기서 네 번째 매개 변수는 정렬 내에서 정렬을 수행하는 데 사용할 함수에 대한 포인터입니다. C ++에서는 이런 종류의 일에 펑터 (함수처럼 보이는 객체)를 사용하는 경향이 있습니다.