【问题标题】:Unclear use of operator double()运算符 double() 的使用不清楚
【发布时间】:2015-12-13 00:26:00
【问题描述】:

我有一个Rectangle 类,其中包含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 传递给构造函数的事实有关?如果有,为什么?

【问题讨论】:

  • 将矩形转换为双精度是什么意思。
  • 我猜是 (double)r 之类的
  • @AlexGoft 不,另一个 Alex 的意思是“这意味着什么逻辑上?”。从表面上看,这个操作似乎毫无意义。
  • 我怀疑他的意思是指区域,因为没有其他理由在示例中包含 getArea() 函数。

标签: c++ operator-overloading implicit-conversion


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    由于您没有为Rectangle 提供operator&lt;&lt; 重载,因此编译器会考虑其他重载,以便将其参数转换为参数类型。

    如果任何重载是模板,则模板参数替换会在重载决议之前发生在它们身上。编译器尝试从提供给函数的参数类型推断模板参数。

    由于模板参数替换失败,不考虑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&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt; 的 typedef。)

    因此,operator&lt;&lt; 的一个重载比任何其他都更好,那就是 double 重载。不是模板,而是类模板的成员函数。

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

    【讨论】:

    • 注意最后一个模板是微不足道的; std::cout 继承自 std::basic_ostream&lt;char, std::char_traits&lt;char&gt;&gt;。不需要模板参数替换。
    【解决方案3】:

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

    未选择字符串重载并且不将其视为歧义的原因是因为字符串的operator &lt;&lt; 是成员函数,不包含在coutmember overload non member overload 集中。如果我们注释掉operator double,我们可以看到we get a compiler error

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

    【讨论】:

    • 那为什么不选择string转换呢?
    • @interjay 我只是在调查。我写答案的时候没有看到那个运营商,
    • 不错的收获。如果有人想解释为什么在不代表数字的类型上实现operator double() 是一种不好的做法,他将很难找到更好的说明:-)
    • std::ostream::operator&lt;&lt;(double) 优于 std::basic_string::operator(basic_ostream&amp;, const basic_string&amp;)
    • @SimonKraemer 并不是说​​一个比另一个更受欢迎,而是另一个根本不被考虑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 2013-02-04
    • 1970-01-01
    相关资源
    最近更新 更多