用户定义的转换运算符到不可访问的基数 class
User-defined conversion operator to inaccessible base class
当基数不可访问时,为什么不允许用户定义转换为基数 class(或对其的引用):protected
或 private
?
当存在 class D
及其 public
基础 B
时,有一个隐式规则将引用绑定到 B
(B&
或 B&&
,可能是 cv 限定的)到 class D
的对象,因此用户定义的到 B&
的转换没有意义。但是当基数 class 为 protected
或 private
时,隐式规则不再适用。那么为什么不允许使用用户定义的转换为 B&
(或 const B&
或 B&&
等)?
这是允许的,标准中没有任何内容禁止这样做。但它只是声明永远不会使用这样的转换运算符。 [class.conv.fct]/1
:
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.
重载解决方案将始终优先于基础 class 构造函数而不是转换运算符,并且永远不会调用转换运算符,因此对于隐式转换来说是不必要的。访问检查总是在重载解析之后完成,因此从不考虑转换运算符。
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
之外访问它,并且您的代码无法编译。
据我所知,这就是重载解析的工作原理。
当基数不可访问时,为什么不允许用户定义转换为基数 class(或对其的引用):protected
或 private
?
当存在 class D
及其 public
基础 B
时,有一个隐式规则将引用绑定到 B
(B&
或 B&&
,可能是 cv 限定的)到 class D
的对象,因此用户定义的到 B&
的转换没有意义。但是当基数 class 为 protected
或 private
时,隐式规则不再适用。那么为什么不允许使用用户定义的转换为 B&
(或 const B&
或 B&&
等)?
这是允许的,标准中没有任何内容禁止这样做。但它只是声明永远不会使用这样的转换运算符。 [class.conv.fct]/1
:
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.
重载解决方案将始终优先于基础 class 构造函数而不是转换运算符,并且永远不会调用转换运算符,因此对于隐式转换来说是不必要的。访问检查总是在重载解析之后完成,因此从不考虑转换运算符。
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
之外访问它,并且您的代码无法编译。
据我所知,这就是重载解析的工作原理。