2017-07-01 35 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

“允许,标准中没有任何内容禁止使用”,您可以阅读“不允许”作为“未使用”。这在措词上只是不准确。 –

相关问题