在gcc-4.8.1中给出以下代码
struct Base
{
};
struct Derive : private Base
{
};
void fn(Base, int);
struct Conv
{
operator Base() const;
operator Derive();
};
int main()
{
Conv c;
fn(c, 0);
return 0;
}
当我给出上面的代码时,我收到了一个错误。我认为编译器会选择Conv::operator Base()
但实际上编译器选择Conv::operator Derive()
但是当我提供以下代码时,编译器选择了Conv::operator Base()
struct Base
{
};
struct Derive// : private Base
{
};
void fn(Base, int);
struct Conv
{
operator Base() const;
operator Derive();
};
int main()
{
Conv c;
fn(c, 0);
return 0;
}
答案 0 :(得分:4)
您的c
对象是非常量的,因此在第一种情况下,Derive
重载是一个精确的常量匹配,仍然可以隐式转换为Base
。在第二个示例中,Derive
无法转换为Base
,因此必须选择直接Base
转化。
答案 1 :(得分:2)
关键是在选择转换序列之前不会检查访问说明符,因此代码感觉如:
struct base {};
struct derived : base {};
struct conv {
operator base() const;
operator derived();
};
void fn(base);
int main() {
conv c;
fn(c);
}
此时有不同的有效转换序列:
const
资格,然后用户转换为基础第二次转换是一个更好的转换序列,它被选中。
这在13.3.3.1/2标准中处理:
隐式转换序列仅涉及参数的类型,cv限定和值类别以及如何转换它们以匹配参数的相应属性。其他属性(例如参数的生存期,存储类,对齐方式或可访问性以及参数是否为位字段)将被忽略。因此,虽然可以为给定的参数 - 参数对定义隐式转换序列,但在最终分析中,从参数到参数的转换可能仍然是不正确的。。