2011-04-09 2 views
7

테스트 코드 작성으로 this query에 대한 답을 얻은 후에 개인/보호 된 상속이 다양한 클래스에서 예외가 수신되는 방식을 변경한다는 사실을 알아야합니다. 이는 매우 놀랍습니다. 답변을 찾으려면 이전 포럼 질문을 참조했고 나는 this similar question을 발견했습니다.상속이 예외 처리에 영향을주는 이유는 무엇입니까?

제게는 virtual 메서드를 사용하여 기본 클래스에 protected 상속을 사용하는 것이 명백합니다. 표준을 제쳐두고, 나는 을 알고 싶었습니다. 왜 가상 메소드 호출이 일 때 C++ 예외 처리가 상속으로 제한 되었습니까? 다음 코드는 설명 :

struct Base { virtual void printError() = 0; }; 
class Derived : protected Base { void printError() { } }; 

int main() 
{ 
try { 
    throw new Derived; 
} 
catch(Base *p) { p->printError(); } // Ideal; but not invoked 
catch(void *p) { ((Base*)p)->printError(); } // Ugly; but only way to invoke 
} 

편집 : 우리가 답변으로 개인 정보 보호 관련을 고려하면, 받아 들였다. 그렇다면 기본 포인터를 수신하는 함수에는 적용 할 수 없지만 기본 포인터를 수신하는 경우에만 catch()을 적용해야하는 이유는 무엇입니까?

+1

+1 좋은 질문입니다. – Nawaz

+3

사소한 일로,'throw' 문에'new'를 사용할 필요가 없기 때문에 그렇게하면 메모리 누수가 발생할 위험이 있습니다. 대신에'throw Derived();'를 사용하고'Base &'참조를 잡아라. 또한, 분명히 왜 나에게 누군가가'protected' 상속을 사용하는지 분명하지 않습니다. 기본 클래스가 가상 메소드를 가지고 있다면, 당신이 뭔가 잘못 생각한 것 같아요. 그리고 마지막으로, 예외 클래스는 일반적으로'std :: exception'을 상속해야합니다. overload'char const * what() const'. –

+0

@Matthieu, 감사합니다. 그러나 위 코드는 데모 목적으로 만 사용되었습니다. 'void '를 붙잡을 수 없으므로 참조에 의한 캐치는 불가능합니다. 그러나 나는 또한 참조로 잡는 것을 더 좋아한다. 내 디자인에 따라 인터페이스 (여기서는'Base') 클래스 메서드 (특히 가상)를 다른 네임 스페이스의 해당 자식에서 호출하면 안됩니다. – iammilind

답변

10

private의 의미에서 그것을 할 수없는 의미가 있습니다 protected 상속은 클래스 또는 클래스 계층 구조 외부의 아무도 상속을 알 수 없다는 것입니다. 이는 수업 외의 어느 누구도 비공개 회원에 대해 알 수없는 것과 같은 방식입니다.
파생 클래스를 기본 클래스로 잡는 것은 포수에게 파생 클래스가 기본 클래스에서 파생 된 것으로 밝혀졌으며 상속의 프라이버시 침해입니다.

+0

좋은 설명으로 +1 좋은 답변! – Nawaz

+0

왜 'catch'중에 만 문제가 발생합니까? 동일한 시나리오가 함수 호출에 적용 가능하면 쉽게 받아 들일 수 있습니다! – iammilind

+0

@iammilind, 잘못, 개인적으로 Base & argument가있는 함수에 파생 클래스를 작성하려고하면 비슷한 오류가 발생합니다. 직접 테스트 해보십시오. – shoosh

5

protected 상속은 Derived만을 의미하며 서브 클래스도 ""임을 의미합니다. main 및 catch 문은이를 "알지 못합니다. 이것은 특정 액세스를 상속하는 지점입니다.

가상 디스패치는이 점에 대해 신경 쓰지 않습니다. 가상 함수를 호출 할 수있는 액세스가있는 경우 가상 디스패치 입니다.

샘플에서

, 그것은 main의 범위에서 다른 곳 Base 것처럼 당신은 Derived를 사용할 수 없습니다 - 그래서 당신이 catch 중 하나

+0

+1 좋은 답변입니다. : D – Nawaz

관련 문제