2011-09-05 6 views
8

나는이 상황에 대한 완전한 답변을 찾기 위해 인터넷과이 스레드를 살펴 보았습니다. 나는 똑똑한 던지는 것을 읽었다. 객체에 대한 포인터는 매우 영리하지 않다. . 나는 왜 이 이런 일인지 이해하고 싶습니다. 나는 상황을 설명 할 것이다.스마트 포인터 및 예외 처리

class Foo 
{ 
public: virtual ~Foo() {} 
}; 

typedef tr1::shared_ptr<Foo> SPFoo; 

class FooInherited: public Foo { }; 

typedef tr1::shared_ptr<FooInherited> SPFooInherited; 

과의이 테스트 코드를 확인하자 :이 간단한 계층 구조를 가정 해 봅시다

int main(int argc, char** argv) 
{ 
    try 
    { 
    throw FooInherited(); 
    } 
    catch(const Foo& f) 
    { 
    cout << "Foo& caught!" << endl; 
    } 
    try 
    { 
    throw SPFooInherited(new FooInherited()); 
    } 
    catch(const SPFoo& f) 
    { 
    cout << "SPFoo& caught!" << endl; 
    } 
    return 0; 
} 

모든 컴파일하지만 런타임에 두 번째 시도 - 캐치 이 실행되지 않습니다. 누군가 왜 나를 설명 할 수 있을까요? 특별히 과 같은 코드 행이 런타임에 완벽하게 작동하는 경우

void function(const SPFoo& f) 
{ 
} 

... 

SPFooInherited fi(new FooInherited()); 
function(fi); 

나는 문제가 SPFooInherited가 SPFoo (FooInherited 푸에서 상속에도 불구하고)에서 상속하지 않는 것을 이해 않지만, 그것은 깊이 컴파일러/무엇인지 알고 싶습니다 함수 호출 예를 다르게하고 RTE 상황을 풀 수없는 예외를 잡을 때. catch 매개 변수가 함수 호출 매개 변수와 같지 않기 때문입니까? 왜 Foo &이 작동하고 SPFoo가 작동하지 않습니까?

대단히 감사합니다.

감사합니다. Iker.

답변

13

귀하의 질문에 언급했듯이 SPFooInheritedSPFoo의 하위 클래스가 아닙니다. 즉, catch(SPFoo const&)SPFooInherited의 인스턴스를 catch하지 않습니다. 반면에 FooInheritedFoo에서 상속되므로 catch(Foo const&)FooInherited의 인스턴스를 잡습니다.

이것을 이해하려면 컴파일러 나 런타임 환경을 특별히 이해할 필요가 없습니다. 그것은 단순히 언어의 일부입니다.

함수 호출이 작동하는 이유는 tr1::shared_ptr에 함수 호출 사이트에서 암시 적 변환을 수행 할 수 있도록 템플릿이 적용된 비공 인 생성자가 있다는 것입니다.

즉 :이 shared_ptr 다른 공유 포인터 형으로 구성 할 수

//Note the lack of explicit 
template<class Y> shared_ptr(shared_ptr<Y> const & r); 

: tr1::shared_ptr는 다음 생성자를 갖는다. 이 생성자의 구현은 FooInherited*에서 Foo*까지의 암시 적 변환을 사용하여 SPFooInherited에 실제로 포인터를 SPFoo에 저장합니다. 이 암시 적 변환이 존재하지 않으면 코드가 컴파일되지 않으므로 관련없는 유형에 shared_ptr 사이의 안전하지 않은 변환이 발생하지 않습니다.

함수 호출과 catch 간의 근본적인 차이점은 함수 인수 초기화시 암시 적 변환이 발생하지만 catch는 단일 유형 (FooInherited is-a Foo이므로 일치 할 수 있음)과 일치한다는 것입니다.

3

SPFooSPFooInherited의 하위 클래스가 아니기 때문에.catch 블록은 캐치 목록에있는 것 또는 캐치 목록에있는 항목의 공용 하위 클래스 만 잡습니다. FooInheritedFoo에서 상속되므로 Foo을 잡으면 FooInherited을 잡을 수 있습니다. SPFooSPFooInherited은 완전히 다른 관련없는 클래스입니다.