簡體   English   中英

C ++ Exception在虛函數上拋出注釋

[英]C++ Exception throw annotations on virtual functions

我看到了以下代碼段:

class Foo
{
public:
        void virtual func() throw (int, float) = 0;
};

class Bar : public Foo
{
public:
        void virtual func() throw(short);      // line 1: compile error "
                                                                      // looser throw specifier"
        void virtual func() throw();                // line 2: can compile
        void virtual func() throw(float, int); // line 3: can compile
        void virtual func() throw(float);        // line 4: can compile
        void virtual func() throw(int);           // line 5: can compile

};

int main(void)
{
        return 1;
}

Q1>是什么意思

void virtual func() throw (int, float) = 0;

Q2>為什么line1無法通過編譯器?

謝謝

讓我們打破這個。 聲明:

void virtual func() throw (int, float) = 0;

有兩個你要問的結構。 =0結構告訴編譯器聲明的函數是'abstract',它告訴編譯器函數不需要在class Foo定義(盡管它可以是 - 但通常不是)並且是class Foo的對象class Foo不能直接創建 - 無論是本地,全局還是new 但是,您可以擁有指向class Foo對象的指針或引用。 某些派生類需要將該函數覆蓋為非抽象函數 - 可以直接創建該類的對象(只要沒有其他抽象函數沒有“具體”)。

throw (int, float)構造是一個異常規范。 這告訴編譯器函數的契約是它只會拋出intfloat類型的異常,如果它拋出異常。 如果函數拋出其他類型的異常,編譯器有義務專門處理(通過調用std::unexpected() )。

現在,如果您嘗試使用以下聲明覆蓋派生類中的該函數:

void virtual func() throw(short);

你說的是函數的契約是如果拋出異常它會拋出short類型的異常。 但是,拋出short並不是被覆蓋函數的契約的一部分,因此編譯器不允許它。

如果你像這樣聲明覆蓋:

void virtual func() throw(float);

你說覆蓋可以拋出一個float ,這是原始聲明的合同的一部分(如果它從不拋出一個不破壞合同的int - 原始合同只說該函數允許拋出一個int ,而不是它必須)。

標准的相關部分是15.4 / 3異常規范:

如果虛函數具有異常規范,則在任何派生類中覆蓋該虛函數的任何函數的所有聲明(包括定義)都應僅允許基類虛函數的異常規范所允許的異常。

請注意,標准明確聲明異常規范不是函數類型的一部分(15.4 / 12),因此函數指針可以指向具有不同異常規范的函數。

您多次定義相同的函數簽名。 不同的throw()限定符不足以消除函數的歧義。

throw()限定符只是意味着指定的函數只能拋出限定符后括號中列出的類型。 但是,這實際上並不會阻止函數拋出。 相反,如果該功能實際上拋出任何未上市的類型,你的程序將終止。

您在基類中定義的函數正在保證 - 它只能拋出一個intfloat 你的第1行是失敗的,因為它會破壞保證,說它會拋出一個short ,這不是上述任何一種。

Q1中的= 0聲明您嘗試創建實例的每個派生類都需要提供自己的聲明和此函數的實現。 基類也可以提供實現,但通常不提供。

named throw語句的含義是聲明一個函數只能直接或間接地拋出那些命名的異常。

所以行:

void virtual func() throw(int, float) =0;

表示無論哪個類繼承此基類型,都只允許拋出int或float。 它不能直接或間接拋出任何其他類型的異常或對象。 如果是,它將調用unexcepted()函數。 默認情況下,它調用terminate()函數。 您可以使用set_unexpected函數重置它,但仍然可以。

通過選擇將這些throw語句添加到您的界面,您實際上是在限制自己。

覆蓋virtual函數時,您提供的任何異常說明符必須至少與您要覆蓋的函數上指定的限制符一樣嚴格。 這可以防止違反基類的異常規范。

由於基類的異常說明符[ throw (int, float) ]不允許拋出short ,派生類不允許拋出short 最多可以允許int和/或float ; 它可能只允許拋出一個或兩個拋出,因為這些可能性中的任何一個都比基類函數的異常規范更具限制性。

暫無
暫無

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

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