2015-01-10 4 views
2

다음 코드가 컴파일되고 작동하는 이유를 정확히 알지 못합니다.연산자에서 순수 가상 함수 호출 <<

#include <iostream> 

struct Base 
{ 
    virtual std::ostream& display(std::ostream& os) const = 0; 
    friend std::ostream& operator<<(std::ostream& lhs, const Base& rhs) 
    { 
     return rhs.display(lhs); 
    } 
}; 

struct A: Base 
{ 
    virtual std::ostream& display(std::ostream& os) const 
    { 
     return os << "A" << std::endl; 
    } 
}; 

struct B: A 
{ 
    virtual std::ostream& display(std::ostream& os) const 
    { 
     return os << "B" << std::endl; 
    } 
}; 

int main() 
{ 
    A a; 
    std::cout << a << std::endl; 

    B b; 
    std::cout << b << std::endl; 
} 

나는 순수한 virtual display 함수를 호출 Base 클래스 내에서 한 번만 operator<<을 정의하고있다. 이 스키마는 대개 파생 클래스에 operator<<을 다시 쓰는 것을 피하기 위해 사용됩니다. 즉 기본 클래스에서 한 번만 정의한 다음 다른 함수 (예 : display())와 함께 가상 디스패치를 ​​사용합니다.

내가 friend std::ostream& operator<<(...)의 구현에 Base 클래스 내부의 순수 가상 함수를 호출 할 수 있어요 왜 Live on Coliru

당신이 설명 할 수 보는가? 나는 이것이 가능하지 않아야한다고 생각했다.

+1

왜 가능하지 않습니까? – immibis

+0

포인터 나 기본 클래스에 대한 참조를 통해 순수 가상 함수를 호출 할 수 없다면별로 유용하지 않습니다. –

+0

어쩌면 내가 뭔가를 놓치고 있지만 순수한 가상 함수를 "호출"할 수는 없지만 과부하 및 파생 클래스에서 호출 할 수는 있습니다. – vsoftco

답변

3

순수 가상 함수를 호출 할 때까지는 함수가 더 이상 순수 가상이 아니기 때문에 순수 가상 함수를 호출 할 수 있습니다. 파생 클래스는이를 추상화하여 "추상화"를 중지해야하기 때문입니다.

컴파일러는 클래스 Base을 인스턴스화 할 수 없다는 것을 알고 있습니다. 즉, 순수 가상 함수에 대해 적절한 재정의를 제공하지 않는 모든 클래스에서 operator <<을 호출 할 수 없습니다. 컴파일러가 호출을 허용하는 이유는 런타임에 구현이 될 것임을 알고 있기 때문입니다.

참고 : 순수 가상 함수를 호출하는 유일한 방법은 기본 클래스의 생성자에서 호출하는 것입니다. 이 함수는 순수 가상이므로 정의되지 않은 동작이 발생합니다. 현대 컴파일러는이 문제에 대해 경고합니다.

+0

예, 혼란스럽게 생각합니다. 참조를 통해 전화를 걸므로 가상 디스패치 규칙이 적용됩니다.이 질문에 부끄럽습니다 ... – vsoftco