2013-03-29 3 views
3

우리는 보통의 클래스 계층이 있습니다함수 포인터가 대체 가능성을 깨고 std :: function이 중단되는 이유는 무엇입니까?

class B 
{ 
public: 
    int x; 
    B() : x(0) {} 
    virtual ~B() {} 
}; 

class D : public B 
{ 
public: 
    int y; 
    D() : y(0) {} 
}; 

그리고 하나 개의 인자를받는 함수를 - 기본 클래스 객체에 대한 참조를.

void b_set(B& b) 
{ 
    b.x = 5; 
} 

그런 다음, I 형 void (D&)의 함수 포인터를 만들고 그 안에 b_set을 저장할. 함수 호출 포인터에 합법적으로 전달 된 모든 객체는 유형 B 여야하므로 유효한 연산이어야합니다. 그러나 허용되지 않습니다.

typedef void (*fp_d_mutator)(D&); 
void fp_test(D& obj) 
{ 
    fp_d_mutator fun = b_set; //invalid conversion from 'void (*)(B&)' to 'fp_d_mutator {aka void (*)(D&)} 
    fun(obj); 
} 

#include <functional> 
typedef std::function<void (D&)> stdfun_d_mutator; 
void stdfun_test(D& obj) 
{ 
    stdfun_d_mutator fun = b_set; //works 
    fun(obj); 
} 

그래서 ...

  • 방법은 유효하지 않은 변환입니까?
  • 왜 변환이 잘못 되었습니까?
  • 허용 된 경우 무엇이 중단 될 수 있습니까?
  • 어떻게 std :: function이 문제를 처음부터 피할 수 있습니까?
+0

이 Cheersandhth. - 알프 @ –

+0

에 적용 g ++ 4.7.2는 MinGW – milleniumbug

+0

흠, 맞아 thinko, SRY –

답변

3

B& 유형의 인수를 사용하는 함수는 D& 유형의 인수를 사용하는 함수가 아닙니다. D&B&으로 변환 될 이지만 동일한 유형은 아닙니다. B&을 포인터로 사용하는 함수에 대한 포인터를 D&에 저장할 수 있다면 컴파일러는 인수를 언제 변환해야하는지 어떻게 알 수 있습니까? 의 일부

std::function의 차이가 호출 서명 (여기 D&) 함수 객체의 유형, (여기 B&) 호출 서명의 일부이다 (변환이 때때로 포인터를 조정 필요합니다)입니다 내부 저장소. 따라서 함수 객체 'operator()을 적용하면 operator()(D&)을 구현하는 코드가 변환을 처리합니다. 은 "작동"않습니다 컴파일러 버전

+0

오, 포인터 조정에 대해 잊어 버렸습니다. std :: function은 저장된 함수를 호출하는 것과 별개로 필요한 변환을 호출합니다. 응, 대답은 만족 스럽지만, 수락하기 전에 잠깐 기다려. – milleniumbug

+0

@milleniumbug - 예, 그렇습니다. 함수 호출 연산자는 명시 적으로 변환을 수행하지 않습니다. 호출 가능한 객체 (이 경우 함수에 대한 포인터)가'std :: function' 객체에 저장되었을 때 할당 연산자는 타입 정보도 저장했다. 호출 가능한 객체를 호출하는 것은 "정상적인"함수를 호출하는 것과 같습니다 : void f (float); int i; f (i);'. 명시 적 변환은 없지만 컴파일러는 필요에 따라 유형을 조정합니다. –

관련 문제