【问题标题】:Difference between << / >> operator overloading and Input/Output functions<< / >> 运算符重载和输入/输出函数的区别
【发布时间】:2016-01-28 09:11:48
【问题描述】:

如果有人能向我解释重载输入/输出运算符之间的区别,我将不胜感激,例如:

friend ostream& operator<<(ostream& ost, const myClass& obj) {
    return ost << obj.x << obj.y;
}

和输出/输入函数如下:

void Output(ostream& ost) {
    ost << x << y;
}

它们用于什么,示例等。一切都是可以接受的。谢谢!

【问题讨论】:

  • 真的没什么不同。 operator&lt;&lt; 在您编写 ost &lt;&lt; obj 时被调用。就是这样 - 它创建了更好的(?)语法并启用链接,因此您一次可以输出多个内容。

标签: c++


【解决方案1】:

如果您想这样称呼它,则使用运算符cout << myObject ...如果您想这样称呼它,可以使用那里的输出:myObject.Output(cout);(但是,谁会呢?)。

但我怀疑您在这里所做的是两种相互竞争的编写

第一个是上面那个,带有friend关键字。

这是另一个版本:

void myClass::Output (ostream& ost)
{
    ost << x << y;
}

ostream& operator<<(ostream& ost, const myClass& obj) 
{
    obj.Output (ost); return ost;
}

通常认为第二个版本更好,因为它避免了使用friend,这被认为是安全风险。允许非成员函数访问私有部分(因此推理)会降低该私有部分的安全性。

这是一篇更详细地讨论这个问题的堆栈溢出文章: Should operator<< be implemented as a friend or as a member function?

...这里讨论“何时使用朋友”的一般理念:https://softwareengineering.stackexchange.com/questions/105766/c-to-friend-or-not-to-friend

我对此的看法是使用friend 并不邪恶,但在不需要时我会避免使用它。在这里,它不是,如第二个版本所示。

【讨论】:

  • 这个答案将受益于“安全违规”部分的基本原理。
  • 我认为“安全违规”听起来比实际情况要糟糕得多。这更像是一种安全“特例”。不理想,但也不是灾难:p
  • 是的。我不在这里做,但它并不可怕。
【解决方案2】:

重载其中任何一个之间确实没有区别(从技术角度来看)。事实上,即使是那些也不是特别的。它们只是可重载的运算符——左移运算符和右移运算符。一般来说,重载运算符的原因是为了提供更好的语法,特别是重载运算符的原因有点传统,基于感知的直觉。

传统上,operator &lt;&lt; 被重载以 发送 东西到其他东西(并称为 insertion operator),operator &gt;&gt; 被重载以 extract em> 来自其他东西的东西 - 被称为提取运算符。在大多数情况下,您要发送到的这个东西output stream,例如std::cout,而您要从中提取的东西是输入流,例如std::cin。考虑到这一点,std::cout &lt;&lt; "Hello\n" 很容易理解为将字符串“Hello\n”发送到输出流,在std::cout 的情况下,通常具有在控制台窗口上打印它的效果。

但是,我们绝对可以将这些重载和重载 >> 交换为插入运算符。在后一种情况下,打印将采用std::cout &gt;&gt; "Hello\n" 的形式。从编译器的角度来看不会有任何区别,但对程序员来说不太直观 - 那些 >> 和

可以为此选择完全不同的运算符。例如,-&gt; 也是一个可重载的运算符,选择它作为提取运算符会很棒。想想这个:std::cin -&gt; str。箭头更加明确。不幸的是,没有可重载的运算符&lt;-,因此缺乏对称性。

另外,必须记住,发明运算符重载是为了允许 C++ 程序在不引入新的保留语言结构的情况下定义新实体。如果 C++ 是一门全新的语言,并且不会站在 C 的肩膀上,那么最终的结果可能会大不相同。

【讨论】:

    【解决方案3】:

    主要区别在于,如果您重载“流操作符”,那么您的类可以被模板函数使用。

    使用标准命名的输出方法会产生类似的效果,但使用流运算符还有一个额外的优势,即它也可以为非类类型定义(即,您可以定义将整数输出到流的含义,但不能为整数定义方法.output)。

    【讨论】:

      【解决方案4】:

      重载&lt;&lt; 运算符将允许您链接输出操作:

      myClass a, b;
      
      ...
      
      cout << a << ' ' << b;
      

      使用您的替代实现,您必须编写:

      myClass a, b;
      
      ...
      
      a.Output(cout);
      cout << ' ';
      a.Output(b);
      

      第一个版本可以更轻松地快速查看输出的格式。这也是在 C++ 中使用流的标准方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-17
        • 2013-12-15
        • 2012-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多