2016-06-03 2 views
4

는 다음과 같은 작업이 예상되는 바와 같이?C++에서 기본 또는 파생 클래스에 대한 포인터를 매개 변수로 가져 오는 함수 포인터를 캐스팅 할 수 있습니까?

struct A {}; 

struct B: public A { 
    int x; 
    }; 

void f(B* o) { 
    std::cout << o->x << std::endl; 
    } 

int main() { 
    B b; 
    b.x = 5; 
    reinterpret_cast<void(*)(A*)>(f)(&b); 
    } 
+1

아마도 가장 기대에 달려 있습니다 ... – luk32

+1

이것은 학문적 인 호기심입니까, 아니면 해결하고자하는 실질적인 문제입니까? –

+1

@RSahu : 그것은 실제로 나를 위해 유용하게 바뀌었지만 가능한 한 예를 그대로 유지하는 것을 선호합니다. –

답변

5

그것의 정의되지 않은 동작은 주조 후 같은 포인터를 사용 : 기능에 대한 모든 포인터가 다른 함수 타입에 대한 포인터로 변환 할 수 있습니다

. 다른 함수 유형에 대한 포인터를 통해 함수를 호출하는 것은 정의되지 않지만 이러한 포인터를 다시 원래 함수 유형에 대한 포인터로 변환하면 원래 함수에 대한 포인터가 생성됩니다. http://en.cppreference.com/w/cpp/language

에서

그래서 귀하의 질문에 대한 대답은 실제로 긍정적 - 당신이 캐스팅 할 수 있지만, 아무것도 더있다.

"캐스팅 만하는 점은 무엇입니까?" - 다양한 기능을 단일 컬렉션에 저장하려는 경우에 유용합니다.

5

5.2.10/6 [expr.reinterpret.cast] 참조 :

함수 포인터가 명시 적으로 다른 유형의 함수 포인터로 전환시킬 수있다. 함수 정의에 사용 된 유형과 다른 함수 유형에 대한 포인터를 통해 함수를 호출하는 효과는 정의되지 않습니다. 말했다

, C++가 널 포인터 역 참조로 할 수 있다는 예를 들어 노트, 그래서 아마 이 올바른 용어되지 않습니다 허용했다.
다음 명령은 너무 컴파일 : 그것은이 문제뿐만 아니라 하나의 허용

reinterpret_cast<void(*)(A*, int)>(f)(&b, 42); 

@ luk32에서 언급 한 바와 같이, 예상 여부로 작동하는지에 상관없이 (이것은 주로, 여러분의 기대에 따라 달라집니다 의견에).

질문에 대한 대답은 입니다. 캐스트가 허용되지만 새 포인터를 통해 함수가 호출되면 정의되지 않은 동작이 발생합니다.

+0

왜 놀랍습니까? 정의되지 않은 것은 아무 일도 일어나지 않고 컴파일되지 않는다는 것을 의미합니다. 기본적으로'reinterpret_cast'를 포함한 모든 것은 제한을 벗어납니다. 나는 타입에 대해서도 비슷한 문장이 있다고 생각한다. – luk32

+0

맞아요, 심지어 _surprising_는 옳은 용어가 아닙니다. – skypjack

+0

"허용"은 실제로 여기에 맞는 단어 선택이라고 생각합니다. 하위 텍스트는 "잘 구성된 C++ 프로그램인가? ..."입니다. 실제로 "허용됨"이라고 지적한 이유에 대해 = "컴파일이 발생합니다" –