2012-01-24 4 views
1

저는 C++을 배웠고 메서드에 대한 포인터와 관련하여 어려움을 겪고 있습니다. 다음과 같이 말합니다 :메서드 포인터 문제

class One { 
public: 
int Add (int a, int b) {return a+b;} 
}; 

typedef int (One::*pAdd) (int, int); 

class Other { 
public: 
int Next (pAdd funct, int c){ return funct (c, 1);} 

}; 

int main(){ 

One one; 
Other other; 

other.Next(one.Add, 2); 

return 0; 
} 

내 MinGW에서보고 한 바와 같이 여러 가지 문제가 있습니다. 첫째, 컴파일러가. * 또는 -> * 사용을 주장하면서 나는 funct를 올바르게 호출하지 않습니다. 이 요청을 통합하는 방법을 모르고 어떤 도움을 환영합니다. 이제는 C 스타일 포인터를 사용하거나 객체를 전달하고 Next에서 메서드를 호출하기 위해 메서드를 정적으로 만들어 문제를 해결할 수 있지만 메서드에 대한 포인터를 이해하고 싶습니다. 기본적으로, 나는 왜 one.Add가 받아 들일 수없는 입력인지에 대해 의아해합니다. 호출 방법은 모호하지 않게 정의되고 (.Add) 내 typedef를 준수합니다. 또한 typedef에서 클래스 (1)의 인스턴스를 제공하므로 메소드가 실행되는 컨텍스트를 제공합니다. 그러나 컴파일러 출력은 마치 구문을 놓치지 않은 것처럼 보입니다. 그러나 개념을 놓친 것처럼. 그렇다면 객체에 대한 메소드에 대한 포인터를 컨텍스트로 단일 인수로 전달하는 방법은 무엇입니까?

+0

... 그들 모두 열고 잘못된 탭에 게시했다. 커뮤니티에 사과 드리며 질문을 어떻게 삭제합니까? –

+2

@gxs가 마이그레이션됩니다. –

+0

안녕 gxs, 귀하의 질문을 StackOverflow로 자동으로 이동할 수 있도록 중재자가 통보됩니다. 이것은 프로그래머이며 소프트웨어 개발에 대한 개념적 질문을위한 사이트입니다. 자세한 내용은 std :: bind/boost :: bind 및 lambda 제안에 대한 [FAQ] (http://programmers.stackexchange.com/faq) –

답변

6

여기서 중요한 문제는 멤버 함수가 개체 인스턴스와 관련이 없으며 약간 다른 서명이있는 함수 포인터에 불과하다는 것입니다. 멤버 함수에 포인터를 호출 할 수있는 객체 인스턴스 : 당신이 멤버 함수를 호출 할 때

그래서, 당신은 두 가지가 필요합니다. 지금

#include <iostream> 

class One { 
public: 
    int Add (int a, int b) {return a+b;} 
}; 

typedef int (One::*pAdd) (int, int); 

class Other { 
public: 
    int Next (One one, pAdd funct, int c){ 
     return (one.*funct)(c, 1); 
    } 
}; 

int main(){ 
    One one; 
    Other other; 

    std::cout << other.Next(one, &One::Add, 2) << std::endl; 

    return 0; 
} 

그리고 it works :

나는 당신의 코드 샘플을 조금 변경되었습니다. 아마 약간 향상시킬 수 있지만 여기에서 가져갈 수 있다고 생각합니다.

c++ faq litePointers to member functions 섹션을 읽는 것이 좋습니다. 이는 매우 잘 설명됩니다.

0

구성원에 대한 포인터가 작동하려면 인스턴스가 필요합니다. 기본적으로 암시적인 this 포인터가되는 더하기 매개 변수를 취하는 함수입니다. 현재 개체의 멤버에 대한 포인터를 통해 함수를 호출하려면 다음과 같은 코드를 사용할 수 있습니다

(this->*funct)(c, 1); 

가 (당신이 유사하지만, 함수 호출없이 멤버 변수에 액세스하는 것).

멤버를 호출 한 객체는 멤버에 대한 포인터의 일부가 아닙니다. 결과적으로 당신은이 같은 뭔가를 얻을 필요가 :이 경우에 당신이 주소를 찍을 때 과부하가 결정 할 수있는 컨텍스트를 제공해야합니다 :이 멤버 함수가 과부하되면 더 흥미로운된다

&One::Add 

. 나는 tupically 이것에 대한 static_cast<>()를 사용

static_cast<int (One::*)(int,int)>(&One::Add) 
1

그럼, 어떻게 하나의 인수로 컨텍스트로 개체와 방법에 대한 포인터를 전달하기 위해?

멤버 함수 포인터 만 사용하면 안됩니다. 구문이 그렇게해야하는 것처럼 보일지라도 그냥 허용되지 않습니다.당신이 기능을 적용 할 객체가 필요 : 특정 객체의 특정 멤버 함수를 호출하는 함수 객체를 만들려면

class Other { 
public: 
    int Next (pAdd funct, One & o, int c){ return (o.*funct) (c, 1);} 
} 

int main(){ 
    One one; 
    Other other; 
    other.Next(&One::Add, one, 2); 
} 

, 다음 일 가능성이 std::bind (또는 boost::bind '당신이 할 수있는 경우를 사용하는 것입니다 아직 t 사용 C++ 11) :

#include <functional> 

class Other { 
public: 
    int Next (std::function<int(int,int)> funct, int c){ return funct (c, 1);} 
}; 

int main(){ 
    One one; 
    Other other; 

    using namespace std::placeholders; 
    other.Next(std::bind(&One::Add, &one, _1, _2), 2); 
} 

또는 람다 : 당신은 여기에 문제의 무리가

other.Next([&](int a, int b){return one.Add(a,b);}, 2); 
+0

+1을 참조하십시오. –

0

가 : one.Add가 회원 쿵푸이다 그리고 당신은 단지 그것을 호출 할 수 없습니다. 에 클래스를 가리키는 포인터가 있어야합니다. 또한 operator.* 또는 operator->* 특수 문자를 사용해야합니다. 바운드 멤버 주소가 일 수도 있습니다.

전체적으로 템플릿 boost/std::bind을 사용하여 을 모두 견딜 수있게하거나 떨어져 있어야합니다. 여기

는 코드를 작업, 수정 :

난 그냥 실현
class One { 
public: 
    int Add (int a, int b) {return a+b;} 
}; 

typedef int (One::*pAdd) (int, int); 

class Other { 
public: 
    int Next (One* one, pAdd funct, int c){ return (one->*funct)(c, 1);} 
}; 

int main(){ 

    One one; 
    Other other; 

    other.Next(&one, &One::Add, 2); 

    return 0; 
}