运算符 double() 的使用不明确

Unclear use of operator double()

我有一个 Rectangle class 转换运算符到 doublestd::string:

class Rectangle
{
public:
    Rectangle(double x, double y) : _x(x), _y(y) {}
    operator std::string ();
    operator double ();
private:
    double _x, _y;
    double getArea() {return _x * _y;}
};

int main()
{
    Rectangle r(3, 2.5);
    cout << r << endl;
    return 0;
}

我不明白为什么调用operator double(),而不是operator std::string()。 据我所知,根据C++ wikibookoperator double 用于将 Rectangle 对象转换为 double.

这是怎么回事?它与 int 传递给构造函数的事实有关吗?如果是,为什么?

您没有将矩形输出到流的运算符。 cout 确实有一个需要 double 的重载,并且您的 class 可以隐式转换为 double 以便选择它。

未选择字符串重载且未将其视为歧义的原因是因为字符串的 operator << 是一个成员函数,不包含在 member overload and non member overload set of cout. If we comment out the operator double we can see we get a compiler error.[=20= 中]

如果我们想要调用 operator string 那么我们需要显式地将 r 转换为字符串。 Live Example

由于您没有为 Rectangle 提供 operator<< 重载,编译器会考虑其他可以将参数转换为参数类型的重载。

如果任何重载是模板,那么模板参数替换会在重载解析之前发生在它们身上。编译器尝试从提供给函数的参数类型中推导出模板参数。

不考虑 string 重载,因为 模板参数替换失败:

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os,
               const std::basic_string<CharT, Traits, Allocator>& str);

模板参数替换不考虑用户定义的转换,因此编译器无法从类型 Rectangle 推导出类型 CharTTraitsAllocator ],所以这个重载不参与重载决议。 (回想一下 std::string 只是 std::basic_string<char, std::char_traits<char>, std::allocator<char>> 的类型定义。)

因此有一个 operator<< 的重载比其他任何一个都更匹配,那就是 double 重载。不是模板,而是 class 模板的成员函数。

basic_ostream<CharT, Traits>& basic_ostream<CharT, Traits>::operator<<(double);

与其他原始类型重载相比,双重重载没有什么特别之处。在这种情况下,它是唯一可用的原始重载。 编译器对 int、char 等的行为相同。

请注意,如果我们有多个原始类型重载,编译器将抛出

error: ambiguous overload for 'operator<<' ...