Stu*_*ons 5 c++ language-design
当基类不可访问时,为什么不允许用户定义的到基类的转换(或对其的引用):protected或private?
当存在一个类D及其public基类时B,存在一个隐式规则将对类的对象B(B&或B&&,可能是 cv 限定的)的引用绑定到该类的对象D,因此用户定义的转换B&没有意义。但是当基类是protected或时private,隐式规则不再适用。那么为什么不允许使用用户定义的转换为B&(或const B&或B&&等)呢?
这是允许的,标准中没有任何内容禁止这样做。但它只是声明永远不会使用这样的转换运算符。[class.conv.fct]/1:
转换函数永远不会用于将(可能是 cv 限定的)对象转换为(可能是 cv 限定的)相同对象类型(或对其的引用),转换为该类型的(可能是 cv 限定的)基类(或对它的引用),或(可能是简历限定的)无效。
重载解析将始终优先使用基类构造函数而不是转换运算符,并且转换运算符永远不会被调用,因此对于隐式转换是不必要的。访问检查始终在重载解析后完成,因此从不考虑转换运算符。
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)
}
Run Code Online (Sandbox Code Playgroud)
对于 (1),复制构造函数B(const B&)比使用转换运算符 ( ) 进行转换更好D,B因此[over.match.ctor]/1将选择构造函数。但直到现在才进行访问检查,并且因为B的复制构造函数是protected,所以它无法编译。
对于(2)几乎完全相同的事情。B& operator=(const B&)由重载决策选择,因为它比调用 的用户定义的转换运算符更匹配D。但现在的B赋值运算符也是protected,因此您无法在 之外访问它D,并且您的代码无法编译。
这就是重载解析的工作原理,据我所知,这是唯一的原因。