我在C ++中发现了一些我认为奇怪行为的东西:私有基类中的类型转换运算符在尝试解析隐式转换时会混淆编译器:
#include <iostream>
struct Base
{
#ifdef ENABLE
operator bool () const { return true; }
#endif
};
struct Derived : private Base
{
operator int () const { return 7; }
};
int main()
{
Derived o;
std::cout << o << '\n';
return 0;
}
没有-DENABLE
,代码编译得很好,并输出7
。使用-DENABLE
,代码不再编译,抱怨模糊的重载。我尝试了gcc-4.6.5
,gcc-4.8.1
和clang-3.3
。令人困惑的是,我显然不能要求(bool)o
,因为Base
是私人基础。
这是预期的行为吗?
答案 0 :(得分:2)
访问控制始终是最后的。从标准引用:
10.2会员名称查找[class.member.lookup]
1会员名称查找确定名称的含义(id-expression) 在一个范围内(3.3.7)。名称查找可能导致歧义 在哪种情况下,该计划是不正确的。对于id-expression,名称 查询从此类的范围开始;对于限定ID,名称 查询从nestedname-specifier的范围开始。 名称查找 在访问控制之前进行(3.4,第11条)。
8如果明确找到重载函数的名称, 在访问控制之前也会发生超载分辨率(13.3)。 通常可以通过使用其类来限定名称来解决歧义 名。
考虑两个运算符的原因是:a)基类转换不会被派生的转换(如果两者都转换为相同的类型,它会被隐藏),b)bool
和{{ 1}}可写入stdout,c)两者都不是比另一种更好的匹配,因此重载决策会产生歧义。即使在访问控制发挥作用之前,这也会产生硬错误。