2011-04-09 55 views
7

雖然在編寫測試代碼時發現this query的答案,但我知道私有/受保護的繼承會改變從各種類接收異常的方式,這非常令人驚訝。爲了找到答案,我提到了前面的論壇問題,我遇到了this similar question爲什麼繼承影響異常處理?

對我來說,使用protected繼承基類有virtual方法是非常明顯的。拋開標準,我想知道爲什麼在虛擬方法調用不是時,C++異常處理受到繼承限制? 下面的代碼片段解釋它:

struct Base { virtual void printError() = 0; }; 
class Derived : protected Base { void printError() { } }; 

int main() 
{ 
try { 
    throw new Derived; 
} 
catch(Base *p) { p->printError(); } // Ideal; but not invoked 
catch(void *p) { ((Base*)p)->printError(); } // Ugly; but only way to invoke 
} 

編輯: 如果我們考慮到隱私方面作爲一個答案;公認。但是爲什麼它僅適用於接收基指針的catch(),而它不適用於接收基指針的函數?

+1

+1好問題。 – Nawaz 2011-04-09 08:49:10

+3

小調,你不必在'throw'語句中使用'new',你只會冒這樣的風險來引入內存泄漏。而是使用'throw Derived();'並通過引用'Base&'捕獲。另外,如果基類有虛方法,爲什麼有人會使用'protected'繼承,我認爲你在這裏出錯了......最後,異常類通常應該從'std :: exception'繼承,並且重載'char const * what()const'。 – 2011-04-09 09:47:21

+0

@Matthieu,謝謝,但上面的代碼只是爲了演示的目的。在這種情況下,通過引用捕獲是不可能的,因爲你無法捕獲'void&';不過,我也更喜歡通過引用捕捉。根據我的設計,我希望Interface(這裏是''Base')類方法(尤其是虛擬的)不應該被其他名字空間中的任何子類調用。 – iammilind 2011-04-09 11:28:20

回答

10

private意義並且protected繼承是類或層次結構以外的人不能知道繼承。這與課堂外沒有人能夠知道私人成員的方式是一樣的。
通過基類捕獲派生類向捕獲者揭示了派生類實際上是從基類派生的,並且是對繼承隱私的違反。

+0

+1好回答,很好的解釋! – Nawaz 2011-04-09 08:51:17

+0

爲什麼只有在catch時纔有問題;當相同的場景適用於函數調用時,它很容易被接受! – iammilind 2011-04-09 09:17:49

+0

@iammilind,錯誤,當您嘗試將私有派生類用於具有基本&參數的函數時,會出現類似錯誤。自己測試一下。 – shoosh 2011-04-22 00:27:59

5

protected繼承僅意味着Derived及其子類「知道」它也是-a Basemain,和catch語句,並不「知道」這一點。這是繼承特定訪問權的一點。

虛擬調度不關心這個 - 如果你有權訪問虛擬函數,那麼使用虛擬調度就是

在您的樣品,你不能用一個Derived,如果它是一個Base其他地方的main範圍 - 因此它是有道理的,你不能做到這一點在catch要麼

+0

+1好答案。 :D – Nawaz 2011-04-09 08:50:25