2017-07-01 102 views
0

爲什麼不允許用戶定義轉換到基類不可用時的基類(或引用):protectedprivate用戶定義的轉換運算符到不可訪問的基類

當有一類D及其publicB,有結合引用BB&B&&,可能CV修飾)到類D的對象的隱式規則,所以用戶定義轉換到B&沒有意義。但是,當基類爲protectedprivate時,隱式規則不再適用。那麼爲什麼不允許使用用戶定義的轉換爲B&(或const B&B&&等)?

+2

您能否舉一個您想要做的轉換的例子,但它被禁止? – dasblinkenlight

+2

這是很不清楚你問的。請舉例說明問題,[mcve]。 – Rakete1111

+0

@dasblinkenlight它不被禁止,但從來沒有被編譯器考慮過,因爲現在的規則。 –

回答

1

這是允許的,標準中沒有任何內容禁止這一點。但它只是說,這樣一個轉換算子將永遠不會被使用。 [class.conv.fct]/1

A轉換函數從不用於轉換(可能CV-合格)對象(可能CV修飾)相同的對象類型(或對它的引用),在(可能CV-合格)該類型的基類(或對其的引用),或者(可能是cv-qualified)void。

重載解析將始終優先於基類構造函數而不是轉換運算符,並且轉換運算符將永遠不會被調用,因此對於隱式轉換是不必要的。訪問檢查總是在超載解析後完成,所以從不考慮轉換運算符。

struct B { 
    B() = default; 
    B(const B&) = default; 
    B& operator=(const B&) = default; 
}; 

struct D : protected B { 
    operator B() { return *this; } 
}; 

int main() { 
    D d; 
    B b = d; // (1) 
    b = d; // (2) 
} 

對於(1),拷貝構造B(const B&)是更好的匹配然後使用轉換運算符([over.match.ctor]/1)轉化DB,以便構造將被選擇。但是現在只是檢查訪問,並且由於B的拷貝構造函數是protected,所以它不能編譯。

對於(2)幾乎完全相同的東西。 B& operator=(const B&)由重載分辨率選擇,因爲它比調用D的用戶定義的轉換運算符更好。但是現在B的賦值運算符也是protected,所以你不能在D之外訪問它,並且你的代碼不能編譯。

這就是重載分辨率是如何工作的,據我所知這是唯一的原因。

+0

「允許,標準中沒有任何內容禁止使用」,您可以閱讀「不允許」作爲「未使用」。這在措詞上只是不準確。 –

相關問題