[英]Smart Pointers and Exception handling
我已經瀏覽了互聯網,這個主題正在尋找我面臨的這種情況的完整答案。 我已經讀過,向對象投擲智能指針並不是很聰明。 我只是想明白為什么會這樣。 我會解釋一下情況。 讓我們想象一下這個簡單的層次結構
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不從SPFoo繼承(即使FooInherited繼承自Foo),但它深深想知道當捕獲異常時,編譯器/ RTE與函數調用示例的不同之處是什么能夠解決de情況。 是因為catch參數與函數調用參數不同嗎? 為什么Foo&works和SPFoo沒有?
非常感謝你提前。
此致,伊克爾。
當你在你的問題說, SPFooInherited
不是一個子類SPFoo
。 這意味着catch(SPFoo const&)
不會捕獲SPFooInherited
實例。 另一方面, FooInherited
繼承自Foo
,因此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
與不相關類型之間的不安全轉換。
函數調用和catch之間的根本區別在於隱式轉換將在函數參數的初始化中發生,但catch只能匹配單個類型( FooInherited
is-a Foo
,因此它將匹配)。
因為SPFoo
不是一個子類SPFooInherited
。 catch
塊只會捕獲捕獲列表中的內容,或者捕獲列表中的內容的公共子類。 FooInherited
從Foo
,因此捕捉Foo
也會讓你抓住FooInherited
。 SPFoo
和SPFooInherited
是完全不同SPFooInherited
相關的類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.