2012-01-07 3 views
4

이 테스트 코드는 struct One은 가상 멤버가없는 일반 형식이고 struct Two : One에는 순수 가상 함수 및 가상 소멸자가 있고 다음과 같은 세 가지 형식을 사용합니다. struct Three : TwoTwo의 인터페이스를 구현합니다.가상 클래스가 아닌 가상 클래스에서 상속하는 올바른 방법

당연히
#include <iostream> 

struct One 
{ 
    ~One() { 
     std::cout << "~One()\n"; 
    } 
}; 

struct Two : One 
{ 
    virtual ~Two() { 
     std::cout << "~Two()\n"; 
    } 

    virtual void test() = 0; 
}; 

struct Three : Two 
{ 
    virtual ~Three() { 
     std::cout << "~Three()\n"; 
    } 

    virtual void test() { 
     std::cout << "Three::test()\n"; 
    } 
}; 

int main() 
{ 
    Two* two = new Three; 
    two->test(); 

    One* one = two; 
    delete one; 
} 

, the output was이 :

세 :: 시험()
~ 한()

모든 소멸자가 가상 ​​만드는 것보다이 다른 문제를 해결하기 위해 어떤 방법이 있나요? 아니면 프로그래머는이 상황에 빠지지 않도록주의해야합니까? 나는 이것을 컴파일 할 때 경고가 없다는 것이 이상하다는 것을 알게된다.

+0

쉬운 수정 : 'One'의 개인 또는 보호 된 상속을 사용하고 선언을 사용하여 기능을 노출하십시오. – Xeo

답변

2

"수정"은 One에 대한 포인터를 통해 개체를 삭제하지 않는 것입니다.

빈번한 문제이거나, 그렇지 않은 경우 클래스 사용 방법에 따라 다릅니다. 예를 들어 표준 라이브러리에는 가상 소멸자가없는 unary_function과 같은 구조체가 포함되어 있지만 이처럼 잘못 사용 된 것은 거의 없습니다.

+0

을 적용하고 'One'의 소멸자를 보호해야합니다. –

1

소멸자를 가상으로 만들어 조심해야합니다. 일부 컴파일러는 이에 대해 경고합니다.

1

파생 클래스에서 작업 소멸자를 사용하려면 가상으로 정의해야합니다. 그것은 유일한 방법입니다.

2

delete one은 개체의 동적 형식이 정적 형식과 일치하지 않으며 정적 형식에 가상 소멸자가 없기 때문에 정의되지 않은 동작을 호출합니다.

이런 문제를 피하는 일반적인 방법은 소멸자를 공개 및 가상으로 만들거나 보호 된 비 가상으로 만드는 것입니다 (이러한 방식으로 사용될 것으로 예상되는 클래스에서).