2011-11-02 2 views
0

가상 함수 및 참조에 질문이 있습니다. 나는 인터뷰를 준비하려고 할 때 퍼즐에서 왔습니다. 나는 잠시 google을했지만 정확한 사례를 볼 수는 없다.참조 캐스팅의 C++ 가상 함수

class A{ 
public: 
virtual void foo() {cout << "A::foo" << endl;} 
}; 

class B: public A{ 
public: 
void foo() {cout << "B::foo" << endl;} 
}; 

class C: public B{ 
public: 
void foo() {cout << "C::foo" << endl;} 
}; 

int main(void){ 
C c; 

B *q; 
q = &c; q->foo(); 
return 0; 
} 

출력에 대한 내 생각은 B :: foo는 수 있지만 대답은 실제로 C :: foo는 것입니다 :

코드

는 다음과 같이 주어진다. 누군가 vtable이 B의 구현을 선택하지 않는 이유를 말해 줄 수 있습니까? 감사합니다

+1

'q'는'C'의 인스턴스를 가리 킵니다. 그래서'foo'의 버전이 호출됩니다. 이유를 물어 질문을 업데이트 할 수 있습니까? * 출력이'B :: foo'라고 생각하는 이유는 무엇입니까? – Ayjay

+0

죄송합니다.이 기사의 C++에서 언급해야합니다. – wilson100

답변

0

AFAIK :

vtable을 사용되면 - A::foovirtual 선언에 의해 강제로이 경우에는 인 - 당신이 선언 유형 중요하지, 항상 가장 구체적인 방법의 방법을 전화 할게 -하는 이 경우 C::foo입니다.

2

foo은 명시 적으로 virtual으로 선언되지는 않았지만 기본 클래스의 가상 함수를 재정의하기 때문에 B에 가상입니다.

q->foo() 통해 호출 된 객체의 대부분의 파생 형은 C하고 서명 void foo()foo위한 C의 최종 overrider는 C::foo 그래서이 호출되는 함수이다.

1

qC 개체를 가리키고 해당 가상 함수 테이블에는 가상 함수 foo이 포함되어 있습니다. 파생 된 클래스에서 클래스에 선언 된 가상 함수는 가상이라는 것을 기억하십시오. 이것은 기본 클래스를 사용하여 파생 클래스에 액세스하는 방법입니다.

0

누군가 vtable이 B 구현을 선택하지 않는 이유를 말해 줄 수 있습니까?

가상 함수가있는 전체 지점이므로 기본 클래스 포인터를 통해 재정의 된 메서드를 호출해도 파생 클래스의 메서드가 계속 호출됩니다.

qB *이지만 C 개체를 가리 킵니다. 따라서 가상 함수를 호출하면 foo()C::foo() 구현이 호출됩니다. 이 A에 같은 선언되기 때문에

비록 foo()

BCvirtual 표시되지 않은, 아직 가상 함수입니다.

B::foo()을 불러 오려면 명시 적으로 호출해야합니다.

q->B::foo(); 
2

foo 경우 가상, 다음 포인터의 종류에 따라 될 것이다라는 기능 및 B::foo()가 호출 될 수 없습니다했다.

foo은 기본 클래스에서 가상으로 정의되었으므로 모든 파생 클래스에서 가상으로 유지됩니다. 그렇다면 호출 된 함수는 포인터 유형이 아닌에있는 을 가리키는 개체 유형을 기반으로합니다.가리킨 객체가 C이므로 호출 된 함수는 C::foo()입니다.

0

foo()는 버전이 그 예입니다 실제로가 q가 가리키는 포인터의 타입 클래스에 정의 된 것이 아니라 호출되는 클래스에 정의 된 것을 의미 가상 함수입니다.

이 즉 하나는 필요가 없다이 이미 클래스 A에서 수행 되었기 때문에 명시 적으로 클래스 B와 C에서 다시 가상으로 기능을 표시 어딘가에 클래스 계층까지 가상으로 표시되면 멤버 함수가 가상이라는 것을 기억