C++ 为什么以下代码出错(关于重载解决方案)

C++ 为什么以下代码出错(关于重载解决方案),c++,overloading,C++,Overloading,给定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::

给定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 derivate()

但是当我给出以下代码时,编译器选择了
Conv::operator Base()


您的
c
对象是非常量的,因此在第一种情况下,
派生
重载是一个精确的常量正确匹配,仍然可以隐式转换为
。在第二个示例中,
derivate
无法转换为
Base
,因此必须选择直接的
Base
转换。

您的
c
对象是非常量的,因此在第一种情况下,
derivate
重载是一个精确的常量正确匹配,仍然可以隐式转换为
Base
。在第二个示例中,
derivate
无法转换为
Base
,因此必须选择直接的
Base
转换。

关键是在选择转换顺序之前不会检查访问说明符,因此代码感觉像:

此时存在不同的有效转换序列:

  • 添加
    const
    限定,然后用户转换到base
  • 用户转换为派生、派生到基本转换
第二个转换是一个更好的转换序列,它被选中

13.3.3.1/2中的标准对此进行了处理:

隐式转换序列只涉及参数的类型、cv限定和值类别,以及如何转换这些参数以匹配参数的相应属性。忽略其他属性,例如参数的生存期、存储类、对齐方式或可访问性,以及参数是否为位字段。因此,尽管可以为给定的参数-参数对定义隐式转换序列,但从参数到参数的转换在最终分析中可能仍然是错误的


关键是在选择转换顺序之前,不会检查访问说明符,因此代码感觉像:

此时存在不同的有效转换序列:

  • 添加
    const
    限定,然后用户转换到base
  • 用户转换为派生、派生到基本转换
第二个转换是一个更好的转换序列,它被选中

13.3.3.1/2中的标准对此进行了处理:

隐式转换序列只涉及参数的类型、cv限定和值类别,以及如何转换这些参数以匹配参数的相应属性。忽略其他属性,例如参数的生存期、存储类、对齐方式或可访问性,以及参数是否为位字段。因此,尽管可以为给定的参数-参数对定义隐式转换序列,但从参数到参数的转换在最终分析中可能仍然是错误的


在这种情况下,为什么您认为编译器应该选择
Base
(c不是
const
)?这几乎就是trickIn的
基本事实,这里有一个详细的解释:在这种情况下,为什么您认为编译器应该选择
base
(c不是
const
)?这几乎就是特里金的
is_base\u事实,这里有一个详细的解释:但是
base
是私有的,
derivate
似乎没有转换成
base
@user2482012:此时不检查访问说明符。只有在选择了转换序列之后,访问说明符才会起作用。我在回答中添加了具体的引用(13.3.3.1/2)。但是
Base
是私有的,
derivate
似乎没有转换为
Base
@user2482012:此时未检查访问说明符。只有在选择了转换序列之后,访问说明符才会起作用。我在回答中添加了具体的引用(13.3.3.1/2)。
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;
}
struct base {};
struct derived : base {};
struct conv { 
   operator base() const;
   operator derived();
};
void fn(base);
int main() {
   conv c;
   fn(c);
}