【问题标题】:What is the use of declaring a function which takes and return "ostream&" rather than overloading operator<<?声明一个接受并返回“ostream&”而不是重载运算符<<的函数有什么用?
【发布时间】:2011-09-19 13:48:55
【问题描述】:

我遇到过这样的函数,而不是重载运算符

例子:

#include <iostream>

class A {
private:
  int number;
public:
  A(int n) : number(n) {}
  ~A() {}
  std::ostream& print(std::ostream& os) const;
  friend std::ostream& operator<<(std::ostream& os, const A a);
};

实现示例:

std::ostream& A::print(std::ostream& os) const {
  os << "number " << number;
  return os;
}

std::ostream& operator<<(std::ostream& os, const A a) {
  os << "number " << a.number;
  return os;
}

现在如果我运行它,我可以在不同的情况下使用不同的功能..例如

int main() {
  A a(1);

  std::cout << "Object.";  a.print(std::cout);
  std::cout << "\n\n";
  std::cout << "Object." << a;
  std::cout << "\n\n";

  return 0;
}

输出:

Object.number 1

Object.number 1

似乎没有需要打印功能的情况,因为您只能单独使用或在“cout 链”的开头使用,但不能在中间或结尾使用,这可能使其无用。使用函数“void print()”不是更好吗(如果没有找到其他用途)?

【问题讨论】:

  • 这个用途是真的烦我。我看不出有什么正当理由。
  • 这不太正确。您可以嵌套函数而不是链接它。 a.print(std::cout &lt;&lt; "Object.");
  • 我会被a.print(a.print(std::cout &lt;&lt; "before" ) &lt;&lt; "in between" ) &lt;&lt; "after"; 激怒。不过。

标签: c++ operator-overloading


【解决方案1】:

继承层次结构发挥作用是有意义的。您可以将print 方法设为虚拟,并在基类的运算符中,委托给虚拟方法进行打印。

【讨论】:

  • 谢谢。甚至认为它不需要是虚拟的,应该像欧内斯特在另一个答案中所写的那样使用我理解你的观点。很有帮助,谢谢。
【解决方案2】:

如果operator&lt;&lt;() 看起来像真的会更有意义

std::ostream& operator<<(std::ostream& os, const A a) {
    return a.print(os);
}

那么operator&lt;&lt;() 就不需要成为朋友了。

【讨论】:

  • 感谢您提供的代码示例。这是完全有道理的,不过你回答问题的方式有点奇怪:)如果不是因为它在“答案”下,我会认为它更像是对我的例子的评论;)
【解决方案3】:

可以用作 cout 链起点的函数听起来肯定比 不能 的函数更有用,在所有其他条件相同的情况下。

我已经使用您描述的签名实现了几个函数,因为operator&lt;&lt; 只是一个名称,有时我需要以多种不同的方式流式传输对象。我有一种用于打印到屏幕的格式,以及另一种用于保存到文件的格式。对两者都使用&lt;&lt; 并非易事,但为至少其中一项操作选择一个人类可读的名称很容易。

【讨论】:

    【解决方案4】:

    operator&lt;&lt; 的使用假定只有一种合理的方式来打印数据。有时这是真的。但有时有多种有效的方式来输出数据:

    #include <iostream>
    using std::cout; using std::endl;
    int main()
    {
      const char* strPtr = "what's my address?";
      const void* address = strPtr;
    
      // When you stream a pointer, you get the address:
      cout << "Address: " << address << endl;
    
      // Except when you don't:
      cout << "Not the address: " << strPtr << endl;
    }
    

    http://codepad.org/ip3OqvYq

    在这种情况下,您可以选择其中一种方式作为方式,其余的使用其他功能(print?)。或者您可以只使用print。 (或者您可以使用流标志来触发您想要的行为,但这更难设置和一致使用。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 2018-03-31
      相关资源
      最近更新 更多