2011-09-05 23 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; 
} 

すべてがコンパイルされますが、実行時に第二のtry-catchは は実行されません。誰かがなぜ私を説明することはできますか?具体的には、 のようなコード行が実行時に完全に正常に機能する場合は特にそうです。

void function(const SPFoo& f) 
{ 
} 

... 

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

私はこの問題は、SPFooInheritedは(FooInheritedがfooから継承していても)SPFooから継承していないということですが、それは深く/ RTEは、関数呼び出しの例とは異なるコンパイラやっていることを知っているしたいことを理解しません状況を解決できない例外をキャッチするとき。 catchパラメータが関数呼び出しパラメータと同じではないためですか?なぜFoo &が動作し、SPFooが動作しないのですか?

ありがとうございます。

よろしくお願いします。 Iker。

答えて

13

ご質問のとおり、SPFooInheritedSPFooのサブクラスではありません。つまり、catch(SPFoo const&)SPFooInheritedのインスタンスをキャッチしません。一方、FooInheritedFooから継承されているため、catch(Foo const&)FooInheritedのインスタンスをキャッチします。

これを理解するには、コンパイラや実行時環境を特別に理解する必要はありません。それは単に言語の一部です。

関数の呼び出しが機能する理由は、tr1::shared_ptrに、関数呼び出しサイトで暗黙的な変換が行われるようにテンプレート化された非明示的なコンストラクタがあることです。

ある:tr1::shared_ptrは、次のコンストラクタを有する。

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

これはshared_ptrは異なる共有ポインタ型から構成されることを可能にします。このコンストラクタの実装では、FooInherited*からFoo*への暗黙的な変換が、SPFooInheritedのポインタを実際にSPFooに格納することに依存しています。この暗黙的な変換が存在しない場合、コードはコンパイルされないので、無関係な型へのshared_ptrの間の安全でない変換は発生しません。

ファンクションコールとキャッチの基本的な違いは、関数の引数の初期化で暗黙的な変換が行われることですが、キャッチは単一の型(FooInherited is-a Foo)と一致するためです。

3

SPFooSPFooInheritedのサブクラスではないためです。catchブロックはキャッチリストにあるものだけをキャッチします。キャッチリストにあるものの公開チャイルドクラスです。 FooInheritedFooから継承しているので、FooをキャッチするとFooInheritedをキャッチできます。 SPFooおよびSPFooInheritedは完全に異なる関連のないクラスです。