【问题标题】:error in overloading ostream operator c++重载ostream运算符c ++时出错
【发布时间】:2014-04-24 15:55:47
【问题描述】:

我正在重载我的类的 ostream/istream 运算符函数友元函数,但它给出了错误: ostream 没有命名类型。 没有或有头文件#include<iostream> 它给出错误

date.h:24:9: error: ‘ostream’ does not name a type friend ostream& operator<< (ostream &out, Date &today);

【问题讨论】:

  • std::ostreamusing namespace std;
  • std::ostreamusing namespace std; 一般不好。
  • 没明白你的意思。

标签: c++ operator-overloading


【解决方案1】:

名称ostream 位于std-命名空间中,因此需要引入该名称。侵入性最小的方法是明确限定它:

friend std::ostream& operator<< ....
       ^^^

另一种方法是使用using- 或using namespace- 指令。它们允许您将名称导入到翻译单元的其余部分:

using std::ostream; // cherry-pick the names
friend ostream& operator<< ....

using namespace std; // fire a shotgun with a huge and growing bunch of names
friend ostream& operator<< ....

这些各有优缺点:

  • 名称变得更短,在上下文中可能更易读
  • 当其他命名空间定义相同的名称时,可能会出现名称冲突(例如 std::powawesome_math_lib::pow)。

一个公认的良好 C++ 代码的经验法则是永远不要在头文件的全局命名空间中使用 usingusing namespace,并且在源文件中要小心。

许多人还同意std:: 如此简短和标准,以至于他们从不使用usingusing namespace(函数内除外),而只是坚持输入std::...

【讨论】:

  • 另一个考虑是根本不要使用friend。我倾向于在类中定义一个公共成员函数并使用它。示例:std::ostream &amp;printTo(std::ostream &amp;out) { ... }myclass 的成员函数,然后 std::ostream &amp;operator&lt;&lt;(std::ostream &amp;out, myclass &amp;me) {return me.printTo(out); } 是函数。在我看来,这比使用friend 更好地保留了myclass 实现的隐私。
  • @Edward:我不确定。使用friend,您可以明确限定某个函数,并且只有该函数才能进行私有访问,该函数可以被视为接口的一部分。我看不出添加 printTo 函数的实际区别,除了后者增加了接口的大小,因此倾向于增加更紧密耦合的可能性。
  • 哦,措辞似乎不准确。序列化不一定是打印。考虑使用流操作符通过网络克隆对象;我不会觉得printOn 太直观了。
  • 问题在于friend 函数可以访问类中的所有内容,包括受保护的和私有的数据成员。这很容易通过提供一个成员函数来避免。如果名字困扰你,选择别的。我发现我 99% 的时间都用于打印,因此大约 20 年来一直使用 printTo 作为此类功能的名称。
  • @Edward:很好的一般性建议,但在这里没有达到目标。要使您的类符合流 IO 接口,您需要重载operator&lt;&lt;(ostream&amp;,T);作为会员是没有办法的。您不会通过引入新成员重载来改善这种情况。但是,当我们现在更喜欢引用而不是争论时:“你不能将人们从他们没有推理到的位置中推理出来。” -- Ben Goldacre(发现于goodreads.com/quotes/tag/argument
【解决方案2】:

更改您的声明和实现以使用类型的完全限定名称:

std::ostream& operator<<(std::ostream& os, Date& d)

避免使用using namespace std;,因为它可能(并且很可能会)导致命名冲突 - 尤其是在头文件中使用时(big no-no)。

【讨论】:

    【解决方案3】:

    您必须使用 std 指定命名空间

    std::ostream
    

    在您的代码中。

    另一种方法是

    using namespace std;
    

    但这不是首选。

    【讨论】:

      【解决方案4】:

      您需要包含标题 &lt;iostream&gt; 并使用限定名称

      std::ostream
      

      或包含指令

      using std::ostream;
      

      甚至

      using namespace std;
      

      输出流的标准类ostream在名称空间std中声明。

      【讨论】:

      • 当提到它作为替代时,请不要使用命名空间std并发出警告。
      猜你喜欢
      • 2020-02-10
      • 1970-01-01
      • 1970-01-01
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多