2013-08-10 2 views
1

그리고 다음 코드에서 함수 앞에 "&"을 사용해야하는 이유는 무엇입니까?가상 함수에 대한 포인터가 비가 상 포인터에 대한 포인터와 다른 점은 무엇입니까?

void (Mammal::*pFunc)() const=0; 
pFunc=&Mammal::Move; 

Move()는 기본 클래스의 가상 함수이고 pFunc는이 클래스의 가상 함수에 대한 포인터입니다. 왜 "&"을 사용해야합니까? 가상 기능의 일부 특수 속성에 따르면? 아니면 단순히 구문입니까?

+1

구성원 함수에 대한 포인터를 사용하면 일반적으로 잘 끝나지 않습니다. –

+0

자세한 내용을 확인하십시오. – seanmcl

+3

표준에 그렇게 쓰여 있기 때문에'&'를 사용해야합니다. –

답변

1

일반 함수는 주소만으로 호출 할 수 있으므로 일반 함수를 가리키는 포인터는 단지 주소입니다.

비 가상 함수는 주소 (물론 컴파일러가 사용하는 메커니즘에 의해 전달 된 this 포인터)를 사용하여 호출 할 수도 있으므로 비 가상 함수에 대한 포인터는 단지 주소 일 수 있습니다 .

가상 함수는 컴파일러 관련 메커니즘 (일반적으로 개체의 알려진 오프셋에서 vtable로, 함수의 주소는 테이블로 인덱싱 됨)에서 찾아야하며 가상의 포인터 함수는 객체의 실제 유형에 따라 호출 할 실제 함수가 무엇인지 결정하는 데 필요한 정보를 포함해야합니다.

그러나 구성원 함수에 대한 포인터는 가상 함수와 가상 함수를 모두 처리 할 수 ​​있어야하므로 둘 모두에 적합한 메커니즘을위한 충분한 공간이있을 것이며 런타임 호출은 저장된 데이터를 확인하여 무엇을 해야할지.

일부 컴파일러는 확실한 방법으로 확실하게 을 지정하지 않으면 포인터를 가상 함수에 대한 포인터를 포인터에 저장하면 컴파일러에서 더 작은 포인터 표현을 생성하고, 나중에 약속을 어기면 곤경에 처하게됩니다.

&이 필요한 이유는 필수입니다. 마이크로 소프트의 초기 C++ 컴파일러는 &을 필요로하지 않았으며 (클래스 이름을 필요로하지 않았으며, 생략했다면 현재 객체 클래스의 멤버 함수에 대한 포인터를 얻을 수 있습니다); 그들은 규칙을 없애라는 제안에 관해 이야기했지만 어디에도 없었습니다.

+0

가상 멤버 함수에 대한 포인터는 일반적으로 썽크에 의해 처리되므로 모든 멤버 함수 포인터가 동일한 표현을 사용한다고 생각했습니다. 회원 데이터 포인터는 드래곤이 사는 곳입니다. –

+0

@AlanStokes - 일부 구현 일 수 있습니다. 그래도 필수는 아닙니다. 이런 종류의 세부 사항에주의를 기울인 지 수년이 지났기 때문에 최신 구현 기술이나 널리 사용되지는 않았습니다. –

0

&은 주소 연산자입니다. C 언어에서는 C++에서이 함수의 이름을 간단하게 지정할 수 있지만 정규화 된 함수 이름과 함께 사용해야합니다.

올바르게 기억하면 가상 함수의 주소를 가져올 때 컴파일러에서 실제로 중간 함수를 생성합니다.이 함수의 주소는 대신 사용됩니다. 해당 중간 함수가 호출되면 사용자가 지정한 가상 함수가 호출됩니다.

+0

C++에서 &와 클래스 이름은 멤버 함수에 필요합니다. C에는 멤버 함수가 전혀 없으므로 멤버 함수를 참조하는 구문이 없습니다. 두 언어 모두 &가없는 비 멤버 함수를 참조 할 수 있습니다. –

0

첫 번째 줄에서 pFunc는 가상 함수에 대한 포인터가 아니며 인수를 취하지 않고 void를 반환하는 Mammal의 const 메서드에 대한 포인터입니다. 그런 다음 해당 포인터에 0을 할당합니다.

'&'연산자는 클래스 범위에서 Mammal :: Move 메서드의 주소를 제공하며 멤버 함수 포인터에 할당하는 데 적합합니다.

표준에서는 '&'연산자가 필요하지만 컴파일러는 필요하지 않습니다.

+1

컴파일러는 표준을 얼마나 잘 표현하는지에 차이가 날 수 있지만, 표준에서는 반드시 '&'on memberfunctions가 필요합니다. –

+0

좋은 지적. 그 문장을 좀 더 명확하게 수정했습니다. – AndyL

관련 문제