2013-07-22 3 views
0
#include <iostream> 
using namespace std; 

class B 
{ 
    B(); 

public: 
    virtual void print()=0; 
}; 

void B::print() 
{ 
    cout << "B::print"; 
} 

int main() 
{ 
    B *bp; 
    bp->B::print(); /* Type-A works fine */ 
    bp->print();  /* Type-B segmentation fault */ 

    return 0; 
} 

위 코드에서 'bp'를 통해 순수 가상 함수를 호출하려고합니다. 주 기능에는 두 가지 유형의 호출 (Type-A, Type-B)이 있습니다. 내 질문은 A가 작동하지만 B가 작동하지 않는 이유입니다. 또한 왜 컴파일러는 객체를 만들지 않고 비 정적 함수를 호출 할 수 있습니다.순수 가상 함수의 이상한 동작

+0

Re : "* 컴파일러는 개체를 만들지 않고 비 정적 기능을 호출 할 수있는 이유는 무엇입니까?"컴파일러에서 사용자가 수행중인 작업을 알고 있다고 가정하기 때문입니다. 컴파일러가'bp'가 일반적인 경우에 유효한 것을 가리키는 지 확인하는 간단한 방법은 없습니다. –

+0

경고 수준에 따라'경고 C4700 : 초기화되지 않은 지역 변수 'bp'used'와 같은 것이 보일 것입니다. – Derek

답변

4

두 가지 모두 정의되지 않은 동작이므로 아무런 문제가 발생하지 않습니다. bp은 초기화되지 않았기 때문에 메서드를 호출하거나 역 참조를 사용하는 것은 불법입니다.

5

bp 유효한 개체를 가리 키지 않아 정의되지 않은 동작이 발생합니다. 이 경우 A works but B doesn't은 완전히 정의되지 않은 동작입니다. bp은 추상적 유형이기 때문에 B 유형의 객체를 가리킬 수 없습니다. 다른 클래스를 파생하고 print을 구현 한 경우 해당 자식 객체에서 bp을 가리킬 수 있습니다.

1

점 : B::print()이 명시 적으로 부여하고 유효한 포인터를 가지고 있으며, 함수 자체가 *this 포인터를 포함하지 않습니다 때문에

  1. bp->B::print()가 작동하지 않을 수 있습니다. 그것은 B::print(bp)으로 번역되고 bp은 무시됩니다.

  2. bp->print() 코드는 vptr (대상이 bp) 존재하지 않으므로 코드가 작동하지 않을 수 있습니다. vptrvtable에 잘못된 위치를 지정하고 함수 호출이 실패합니다. 그것은 sth로 번역됩니다. like : bp->vptr->vtable['print'](bp)' and you can see both vptr and vtable`이 정의되지 않았습니다.