【问题标题】:Can ostream overloading be a function member?ostream 重载可以是函数成员吗?
【发布时间】:2012-05-31 21:48:27
【问题描述】:

我有一个类Counter,我想重载operator << 以输出Counter 的数据成员。我试图让 ostream 重载一个成员函数:

Counter{
public:
    std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
    int count_;
};

std::ostream& Counter::operator<<(std::ostream& outStream, const Counter& c){
    outStream << c.count_;
    return outStream;
}

但是g++编译器总是输出同样的错误:

‘std::ostream&amp; Counter::operator&lt;&lt;(std::ostream&amp;, const Counter&amp;)’ 必须只接受一个参数

但是,如果我将重载函数更改为类的朋友,它工作得很好,像这样:

Counter{
public:
    friend std::ostream& operator<<(std::ostream& outStream, const Counter& c);
private:
    int count_;
};

std::ostream& operator<<(std::ostream& outStream, const Counter& c){
    outStream << c.count_;
    return outStream;
}

这是否意味着流运算符重载不能是类的成员函数?

【问题讨论】:

  • 它没有必须成为朋友 - 如果你的班级设计得很好,你可以使用公共接口......
  • 如果你想访问非公共成员,它必须是朋友,就像任何其他功能一样; operator&lt;&lt; 这里没什么特别的。
  • @ildjarn 但它可以是成员函数吗?
  • @Brian : 不,因为第一个参数必须是流,并且在成员函数中,第一个(隐式)参数始终是指向类类型的指针(即this)。
  • @ildjarn 我明白了,非常感谢!

标签: c++


【解决方案1】:

如果您将 ostream 运算符放在类本身中,那么它将无法按您期望的方式工作。这将是一个成员函数,意味着调用它必须这样做:c.operator&lt;&lt;("output") 这显然不是你的意思。要使其按您期望的 ostream 运算符工作,它必须在类之外。您可以通过使其成为朋友来做到这一点,或者只是将其放在类之外并使用 getter(访问器)来输出数据。

【讨论】:

  • 中缀符号对成员操作符来说工作得很好......但调度是基于左侧操作数完成的。
【解决方案2】:

添加一个public查询方法,返回count_的值,那么就不必是friend了:

Counter{
public:
    int count() const { return count_; }
private:
    int count_;
};

std::ostream& operator<<(std::ostream& outStream, const Counter& c){
    outStream << c.count();
    return outStream;
}

【讨论】:

  • 我的意思是..operator&lt;&lt; 可以成为 Counter 的函数成员吗?
  • 暴露内部成员是个坏主意(这会导致与其他代码的过度耦合)。最好提供一个print() 方法,该方法将流作为参数,然后让对象自行序列化。
  • @LokiAstari,内部成员不在这里公开。
  • 在调用count() 方法时,您将接口绑定到提供int 类型,因此您公开了实现细节count_。 Getter 非常可怕,因为它们将您的类与使用它的代码紧密耦合在一起。提供 print() 方法可以解耦类,因为它不会暴露内部实现。
  • @LokiAstari,我要做的唯一更改是将方法重命名为 value() 或类似名称。 Counter 为其客户端提供一些服务,并通过其public 接口提供服务,否则几乎无用。拥有一个访问类的public 接口的operator&lt;&lt; 不会比使用它的任何其他代码耦合它。我不喜欢print() 方法的建议,因为如果更多Counter 实例被输出到流中,这将如何出现在调用站点上。
【解决方案3】:

它不一定是朋友,但它不能是会员。成员运算符仅在它们位于与左侧操作数对应的类中时才起作用。

【讨论】:

  • 非常感谢。做我才有意义。
【解决方案4】:

不幸的是,流输出运算符 (

在您的第一个 Counter 类中,您声明了该类的一个似乎无效的成员函数。在 Counter 类的第二个示例中,您声明

Wikipedia Operators in C and C++ 有一个很好的可能的运算符重载列表,包括类中的 CounterInstance << cout;,这是违反直觉的。

【讨论】:

    猜你喜欢
    • 2015-01-15
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多