2012-03-11 94 views
4

此代碼在VS2008中生成C2248 : 'A::B::ExceptionB' : cannot access private class declared in 'class A::B'爲什麼編譯器不會抱怨catch子句?

#include <iostream> 

class A 
{ 
    class ExceptionA{}; 

    class B 
    { 
     class ExceptionB{}; 
     public: 
     B(); 
    }; 

    public: 
    A(int); 

}; 

A::B::B() 
{ 
    throw ExceptionB(); 
} 

A::A(int i) 
{ 
    i % 2 ? throw ExceptionA() : throw A::B::ExceptionB();  // C2248 !! 
} 

int main() 
{ 
    try 
    { 
     A a(3); 
    } 
    catch(A::ExceptionA&) 
    { 
     std::cout << "A::ExceptionA" << std::endl; 
    } 
    catch(A::B::ExceptionB&) 
    { 
     std::cout << "A::B::ExceptionB" << std::endl; 
    } 
} 

當然,如果我讓類ExceptionB{}公衆B,代碼編譯。

但我不明白爲什麼編譯器簡化版,在main()抱怨的2個catch子句,爲A::ExceptionAA的私有類和A::B::ExceptionBA::B私有類。

回答

3

問題的措辭有些奇怪,所以我假設你問爲什麼

i % 2 ? throw ExceptionA() : throw A::B::ExceptionB(); 

不能編譯,而

catch(A::ExceptionA&) 
catch(A::B::ExceptionB&) 

一樣。

如果你看看你方便的花花公子C++標準(第11章,第4段)的副本,它說以下內容:

應當指出的是,訪問成員和基類這是受控的,而不是他們的知名度。 成員的名稱仍然可見,並且當這些成員和基類不可訪問時,仍然會考慮隱式轉換爲基類。

再在上面不同的是,在第一種情況下,你想調用A::ExceptionAA::B::ExceptionB成員 - 爲異常的構造函數。但在catch語句中,您沒有訪問任何一個成員;你只能訪問類型名稱。


這就是說,我仍然認爲這是MSVC++中的一個錯誤。該標準還說,在第15.6段第1段中提到:

如果catch子句中的異常聲明具有類類型,並且發生catch子句的函數無法訪問該類的析構函數,該計劃是不健全的。

您的示例似乎違反了,但MSVC++沒有投訴就接受它。

+0

你說得對。如果我用'catch(A :: ExceptionA&a)'替換'catch(A :: ExceptionA&)',編譯器會抱怨。您在標準中提到了第15.6章,但我找不到它,至少在標準最新草案N3225中找不到。你能確認15.6段落1嗎? – Belloc 2012-03-11 15:27:38

+0

@ user1042389:我在這裏查看C++ 03。 – 2012-03-11 15:31:01

+0

謝謝。我給你的答案的功勞。 – Belloc 2012-03-11 15:33:10

1

這兩個例外都是私有的,g ++,clang和EDG都抱怨它。也就是說,像你一樣使用它們可能是C++中的一個錯誤,但是你的編譯器似乎在允許代碼時是錯誤的。但是,有關異常處理的部分實際上並未明確指出被捕獲的異常需要具有特定的訪問權限(畢竟,私有類可以在'A'的成員中訪問)。我想這導致開發人員不檢查此訪問權限。

相關問題