爲什麼不允許用戶定義轉換到基類不可用時的基類(或引用):protected
或private
?用戶定義的轉換運算符到不可訪問的基類
當有一類D
及其public
基B
,有結合引用B
(B&
或B&&
,可能CV修飾)到類D
的對象的隱式規則,所以用戶定義轉換到B&
沒有意義。但是,當基類爲protected
或private
時,隱式規則不再適用。那麼爲什麼不允許使用用戶定義的轉換爲B&
(或const B&
或B&&
等)?
爲什麼不允許用戶定義轉換到基類不可用時的基類(或引用):protected
或private
?用戶定義的轉換運算符到不可訪問的基類
當有一類D
及其public
基B
,有結合引用B
(B&
或B&&
,可能CV修飾)到類D
的對象的隱式規則,所以用戶定義轉換到B&
沒有意義。但是,當基類爲protected
或private
時,隱式規則不再適用。那麼爲什麼不允許使用用戶定義的轉換爲B&
(或const B&
或B&&
等)?
這是允許的,標準中沒有任何內容禁止這一點。但它只是說,這樣一個轉換算子將永遠不會被使用。 [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
)轉化D
到B
,以便構造將被選擇。但是現在只是檢查訪問,並且由於B
的拷貝構造函數是protected
,所以它不能編譯。
對於(2)幾乎完全相同的東西。 B& operator=(const B&)
由重載分辨率選擇,因爲它比調用D
的用戶定義的轉換運算符更好。但是現在B
的賦值運算符也是protected
,所以你不能在D
之外訪問它,並且你的代碼不能編譯。
這就是重載分辨率是如何工作的,據我所知這是唯一的原因。
「允許,標準中沒有任何內容禁止使用」,您可以閱讀「不允許」作爲「未使用」。這在措詞上只是不準確。 –
您能否舉一個您想要做的轉換的例子,但它被禁止? – dasblinkenlight
這是很不清楚你問的。請舉例說明問題,[mcve]。 – Rakete1111
@dasblinkenlight它不被禁止,但從來沒有被編譯器考慮過,因爲現在的規則。 –