2014-06-15 61 views
1

衆所周知,我們可以使用純虛析構函數,就像這樣:如果從析構函數調用純虛函數是UB,爲什麼我們可以使用純虛擬desrtuctors?

struct A { 
    virtual ~A() = 0; 
}; 
A::~A() {} 

struct B : A {}; 

因爲標準說,在10.4 [class.abstract] p2

純虛函數如果調用需要被定義只用...( 12.4 [class.dtor])

後來在12.4 [class.dtor] p9

析構函數可以聲明爲虛擬的(10.3)或純虛擬的(10.4);如果程序中創建了該類的任何對象或任何派生類,則應定義析構函數。

什麼意味着上面的代碼是完全有效 - A::~A可以是純虛擬的,它被定義,B::~B隱式調用A::~A

到目前爲止,這麼好。
然後我讀10.4 [class.abstract] p6

成員函數可以從一個構造(或析構函數)一個抽象類的調用;對於從這樣的構造函數(或析構函數)創建(或銷燬)的對象,直接或間接地對純虛函數進行虛擬調用(10.3)的效​​果是未定義的。

但是,這正是我們在這裏所做的 - 我們從析構函數調用純虛函數A::~A

那麼,是不是有某種矛盾?

+0

析構函數是一種特殊情況,因爲即使它是純虛擬的,它仍然必須有一個正文(按照標準)。未定義的部分適用於純虛擬成員函數(可能沒有定義)。 – StoryTeller

回答

3

沒有收縮。

您可以從B的析構函數中調用A的虛擬析構函數。 A析構函數不是B的成員。

標準§9.3

成員函數類的定義中聲明

功能,但不包括與朋友符( 11.3)聲明的那些 ,被稱爲是類的成員函數

該標準規定存在虛擬呼叫時存在未定義的行爲摘要類的析構函數/構造函數(在你的情況下,它將是類A)到它自己的純虛函數中的一個。

[...]的成員函數可以從一個抽象類[構造(或析構函數)被調用...]。

你的引證說析構函數:

  1. 您可以從一個抽象類
  2. 的析構函數從的調用成員函數如果調用純虛方法(用虛擬呼叫)這個抽象類的析構函數,存在未定義的行爲。
+0

以及如果'B'會是一個抽象類呢?那麼它會是UB? – Abyx

+0

不,那裏我不清楚,看到我的編輯。 – quantdev

-2

如果存在虛擬調用(10.3 [class.virtual]),則會發生UB。

對純虛函數進行虛擬調用(10.3)的影響未定義。

但10.3 [class.virtual] P15說

與範圍操作者(5.1)顯式資格抑制虛擬調用機制。

隱式析構函數調用似乎具有明確的限定條件。
至少編譯器肯定不會在那裏做虛擬調用。