포인터를 가상 구성원 기능입니다.그것은 어떻게 일하는가?
-
23-08-2019 - |
문제
다음 C++코드:
class A
{
public:
virtual void f()=0;
};
int main()
{
void (A::*f)()=&A::f;
}
면 나는 추측이라고 말하고 싶&A::f 이 컨텍스트에서는 의미는"주의 구현 f()",없으므로 명시적인 분리 사이의 포인터를 정기적인 멤버의 기능과 가상 구성원 기능입니다.그 때문에 구현되지 않았다 f(),는 것이 컴파일에 오류가 있습니다.그러나,그것은 아닙니다.
그뿐만이 아닙니다.다음 코드:
void (A::*f)()=&A::f;
A *a=new B; // B is a subclass of A, which implements f()
(a->*f)();
이 실제로 부 B:f.
그것은 어떻게 일어나는가?
해결책
회원 기능 포인터에 대한 정보가 너무 많습니다. 기사가 실제로 C ++에서 대의원을 구현하는 것에 관한 것이기 때문에 IIRC는 "잘 행동 한 컴파일러"아래의 가상 기능에 대한 몇 가지 사항이 있습니다.
http://www.codeproject.com/kb/cpp/fastdelegate.aspx
짧은 대답은 컴파일러에 따라 다르지만, 한 가지 가능성은 멤버 기능 포인터가 가상 호출을하는 "펑크"함수에 대한 포인터를 포함하는 구조물로 구현 될 가능성이 있다는 것입니다.
다른 팁
표준이 그것이 어떻게 일어나야하는지 말하기 때문에 작동합니다. GCC로 일부 테스트를 수행했으며 가상 함수에 대해 GCC는 해당 기능의 가상 테이블 오프셋을 바이트로 저장합니다.
struct A { virtual void f() { } virtual void g() { } };
int main() {
union insp {
void (A::*pf)();
ptrdiff_t pd[2];
};
insp p[] = { { &A::f }, { &A::g } };
std::cout << p[0].pd[0] << " "
<< p[1].pd[0] << std::endl;
}
그 프로그램 출력 1 5
-이 두 기능의 가상 테이블 항목의 바이트 오프셋. 그것은 따릅니다 이타늄 C ++ ABI, 그것을 지정합니다.
나는 완전히 확실하지 않습니다,그러나 내 생각에 그냥 일정한 다형성 동작입니다.내 생각에는 &A::f
실제로 의미의 주소는 함수 포인터에서 클래스의 vtable,그리고 당신은 왜 못하고 컴파일러에 오류가 있습니다.공간에서 vtable 은 여전히 할당하고,그 위치에 당신은 실제로 다시 얻.
이것은 감지기 때문에 파생 클래스는 기본적으로 덮어쓰기는 이러한 값으로 포인터를 자신의 기능입니다.이런 이유 (a->*f)()
에서 작동하는 두 번째 예제 f
를 참조하 vtable 서 구현된 파생된 클래스입니다.