簡體   English   中英

C ++:對象切片和異常

[英]C++: object slicing and exceptions

在一次采訪中,我被問到為什么按價值捕獲異常可能是一個問題,我回答說這會導致對象切片。 這就是我在互聯網上找到的,例如: https//www.viva64.com/en/w/v746/

但是現在我正在嘗試進行實驗,但是在按值捕獲時我找不到切片的示例。 切片的常規場景(不是例外)是這樣的:

Derived d1;
Derived d2;
Base& b1 = d1;
Base& b2 = d2;
b1 = b2;

在最后一行中調用Base的賦值運算符,它只復制Derived對象的Base部分。 因此,b1的基礎部分是從d2復制的,而b1的派生部分是從d2復制的。 壞。

但是,當按價值捕獲異常時,這怎么會發生?

我嘗試了這個代碼(同時使用:g ++和Sun CC編譯器):

struct Base
{
    virtual void print() const
    {
        cout << "{ Base: " << m << " }" << endl;
    }

    Base(int _m = 0) : m(_m) {}

    int m;
};

struct Derived : Base
{
    Derived(int _m = 0, int _n = 0) : Base(_m), n(_n) {}

    void print() const
    {
        cout << "{ Base: " << m << ", Derived: " << n << " }" << endl;
    }

    int n;
};

int main()
{
    try
    {
        try
        {
            throw Derived(3, 300);
        }
        catch(Base x)
        {
            cout << "Inner catch: ";
            x.print();
            throw;
        }
    }
    catch(Derived y)
    {
        cout << "Outer catch: ";
        y.print();
    }    
}

輸出是:

Inner catch: { Base: 3 }
Outer catch: { Base: 3, Derived: 300 }

所以我拋出Derived異常,捕獲它的Base BY VALUE並重新拋出,然后捕獲Derived BY VALUE並且一切正常,沒有任何切片。 那個怎么樣?

並且有人可以提供捕獲BY VALUE時的切片示例嗎?

即使catch(Base)對被拋出的Derived對象進行切片,re throw也會使用原始異常對象而不是切片副本。

來自http://en.cppreference.com/w/cpp/language/throw

重新排列當前處理的異常。 放棄當前catch塊的執行並將控制傳遞給下一個匹配的異常處理程序(但不會在同一個try塊之后傳遞給另一個catch子句:它的compound-statement被認為已經'退出'), 重用現有的異常對象 :沒有新的對象。 此表單僅在當前正在處理異常時允許(如果另外使用則調用std :: terminate)。 如果在構造函數上使用,則與函數try-block關聯的catch子句必須通過rethrowing退出。


注意,如果你替換throw; 通過throw x; ,一個Base實例將被拋出並且不會被捕獲,導致調用std::abort() 實際上,切片的Derived不能被未切割(這就是為什么我們通常不喜歡切片,除非它們是披薩切片)被catch (Derived)

作為結論,我堅持“按價值投擲,按(常)引用”) 在這個具體的例子中,你很好地捕捉切片值,但一般情況並非如此。 Serge Ballesta的回答提供了一個值得抓住的例子,導致了麻煩。 快速搜索您最喜愛的搜索引擎可以幫助您找到其他案例,其中捕獲價值正在尋找麻煩。

另一個通過值捕獲異常的問題是它需要異常的完整副本。 如果您接近StackOverflow條件(或已經處理一個條件),則可能處於無法執行復制的用例,並且無法執行catch子句。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM