1

이 나는 ​​제공된 함수 템플릿 사용하는 것을 시도하고있다 :호출 포인터 - 투 - 회원 기능은

template <class Process, class BTNode> 
void postorder(Process f, BTNode* node_ptr) 
{ 
    if (node_ptr != 0) 
    { 
     postorder(f, node_ptr->left()); 
     postorder(f, node_ptr->right()); 
     f(node_ptr->data()); 
    } 
} 

이 내 전화이며, 기능 내가 전달 해요 :

void city_db::print_bst() { 
    postorder(&city_db::print, head); 
} 

void city_db::print(city_record target) 
{ 
    std::cout << target.get_code(); 
} 

이 컴파일 시간 (G ++) 오류 내가 얻을 수 있습니다 :

CityDb.cpp:85: instantiated from here

BinTree.template:80: error: must use ‘.’ or ‘->’ to call pointer-to-member function in ‘f (...)’

make: *** [CityDb.o] Error 1

이것은 기능 템플릿의 라인 f(node_ptr->data());을 참조한 것입니다.

이것은 데이터 구조 프로젝트를위한 것입니다. 함수에 함수를 전달할 필요가 없도록 할당이 수정되었지만 꽤 오랫동안이 문제에 관심이있었습니다. 거의 여기에있는 것처럼 느껴집니다. 나는 Google과 Lab TA를 다 써 버렸다. 그래서 StackOverflow에 아이디어가 있다면 크게 환영 할 것이다.

답변

7

참조하십시오. 먼저 멤버 포인터에서 함수 객체를 만들기 위해 mem_fun을 호출해야하십시오 city_db (암시 적 this 포인터)의 포인터 및 개체가 인쇄 될 :

std::mem_fun(&city_db::print) 

반환 된 함수 객체는 두 개의 인수를 취합니다.) (당신은 city_db :: 인쇄를 만들기 위해 하나 필요

postorder(std::bind1st(std::mem_fun(&city_db::print), this), head); 
+0

이 사실을 이해하는 데 몇 분이 걸렸지 만 한번 클릭하면 완벽하게 이해할 수 있습니다. 그것을 관리 가능한 부분으로 나누어 줘서 고마워. 마지막 라인은 빌드 오류를 해결했습니다. –

3

print을 호출하려면 city_db의 인스턴스가 필요합니다.

전달할 것은 멤버 함수에 대한 포인터입니다 (vtable의 슬롯으로 생각하면됩니다). this 포인터가 필요합니다. 이것을 postorder 함수의 다른 인수로 전달할 수 있습니다.

f(arg); 

당신은 멤버 함수에 대한 포인터를 전달됩니다

template <class Object, class Process, class BTNode> 
void postorder(Object* obj, Process f, BTNode* node_ptr) 
{ 
    if (node_ptr != 0) 
    { 
     postorder(obj, f, node_ptr->left()); 
     postorder(obj, f, node_ptr->right()); 
     ((obj)->*(f))(node_ptr->data()); 
    } 
} 

당신의 문제가 postorder이 방법으로 호출해야하는 함수 객체가 수용 할 수있다 C++ FAQ Lite

+0

http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5 FAQ 섹션에서는 구문을 좀 더 명확하게 만드는 데 도움이되는 정보를 제공합니다. 일반적으로 저는 토마스의 대답을 선호합니다. – Dolphin

+0

아마 그것을 수정할 수 있지만 BinTree를 수정하지 않은 상태로 유지할 수있는 큰 라이브러리로 취급하고 있습니다. 이것은 아래에 무슨 일이 벌어지고 있는지 잘 보여 주며 다음 번에 문제가 있는지 확인하기 위해 맛있는 리소스에 추가해 주셔서 감사합니다. –

0

을 :

std::bind1st(std::mem_fun(&city_db::print), this) 

을 그리고 지금 당신은 그것을 postorder 전화를 할 수 있어야한다 :이 같은 bind1st와이에 처음 바인딩 할 수 있습니다 정적이거나 도시 _db 객체를 제공하십시오. 클래스 상태에 의존하지 않는

void city_db::print(city_record target) 
{ 
    std::cout << target.get_code(); 
} 

서면으로

0

. 정적 함수로 선언하면 컴파일러에서 this 포인터를 호출 할 필요가 없습니다. 주제에 FAQ

+0

이 예제에서는 true이지만 멤버 함수에 대한 포인터의 전체 문제점을 회피합니다. – Dolphin