2014-05-22 3 views
1

클래스 메서드를 첫 번째 포인터를 저장하는 다른 클래스에서 바인딩하려고했지만 항상 다른 값을 제공합니다. 내가 뭘 잘못하고 있니?C++ 함수 : 포인터를 통해 클래스 메서드 바인딩

값으로 클래스 A를 전달하면 (물론 클래스 B를 값으로 저장하도록 수정 한 경우) 작동합니다.

#include <iostream> 
#include <functional> 

using namespace std; 

class A { 
public: 
    A(double a, double b) : a(a), b(b) {} 
    double mul(void) {return a*b;} 

private: 
    double a; 
    double b; 
}; 

class B { 
typedef std::function<double(void)> function; 

public: 
    B(A* ap) : ap(ap) {} 

    function a_mul = bind(&A::mul, ap); 

private: 
    A* ap; 
}; 

int main() { 
    A* a = new A(2,3); 
    B b(a); 

    cout << b.a_mul() << endl; 

    return 0; 
} 
+0

a_mul은 인라인으로 초기화 할 수 없으므로 실행중인 코드와 일치하지 않습니다. a_mul 초기화 외에도 괜찮습니다. 그래서 문제는 보여지지 않은 것에 놓여 있어야합니다 ... – dlf

+1

@dlf "a_mul은 초기화 할 수 없습니다."그렇습니다. C++ 11에 오신 것을 환영합니다. –

+0

@ n.m. 산뜻한! 그러나 Microsoft의 (2012) C++ 11은 아닙니다. : – dlf

답변

4

비 정적 데이터 멤버 이니셜 라이저를 사용하여 a_mul을 초기화하고 있습니다. 초기 값은 ap의 값에 따라 다릅니다. 그러나 ap의 정의는 a_mul의 정의를 따릅니다. 즉, a_mul은보다 먼저 으로 초기화되고 생성자에서는 ap이 초기화됩니다. 초기화가 발생할 때 ap에는 불확정 값이 있으므로 코드에 정의되지 않은 동작이 있습니다. 이 문제를 해결하는

방법 중 하나는 멤버 변수의 정의의 순서를 변경한다 :

class B { 
typedef std::function<double(void)> function; 

public: 
    B(A* ap) : ap(ap) {} 

    A* ap; 
    function a_mul = bind(&A::mul, ap); 
}; 

그러나 더 나은 수정 데이터 멤버, 생성자의 초기화 목록에서 a_mul 초기화의 순서 일 것이다.

class B { 

typedef std::function<double(void)> function; 

private: 
    A* ap; 

public: 
    B(A* ap) : ap(ap), a_mul(bind(&A::mul, ap)) {} 

    function a_mul; 
}; 
+0

해답을 찾아 주셔서 대단히 감사합니다. 해결책이었습니다! – mooattyi