如何正确定义和调用原始运算符<<

How to properly define and call original operator<<

本文关键字:lt 运算符 原始 调用 何正确 定义      更新时间:2023-10-16

请考虑以下示例:

#include <iostream>
class A {
    const int i;
    const int j;
public:
    A(int i_, int j_) : i(i_), j(j_) {}
    std::ostream& operator<<(std::ostream& o) const {
       o << "i is " << i << ", j is " << j;
       return o;
    }
};
std::ostream& operator<<(std::ostream& o, const A& a ) {
    o << "This is A: ";
    a.operator<<(o);
    return o;
}
int main() {
    A a(0,42);
    std::cout << a << std::endl;
    return 0;
}

它将生成以下输出:

This is A: i is 0, j is 42

输出是正确的,但我不喜欢我如何称呼 A 的原始operator<<.

我正在尝试弄清楚如何正确定义该运算符,因此可以这样调用它:

o << "This is A: " << (some magic)a;

而不是

o << "This is A: ";
a.operator<<(o);

我已经尝试了各种方法,但要么我遇到了歧义问题,要么得到了std::cout和断开字符串的地址。请注意,A::operator<< 的结果std::ostream&是我的测试的残余。在上面的例子中,使用 void 就足够了。

是否可以不创建一个从A类派生的中间类B并定义自己的运算符<<(class NiceOutputOfA : public A {...};(?

在类中定义的二元运算符始终将类作为左侧操作数。这意味着您无法在类中实现流插入/提取。

可能最常见的方法是将运算符实现为类中内联定义的friend

另一种合理的常见方法是在类中提供一个命名的流函数,以及一个调用该函数的类外流运算符。您几乎做到了,但将该函数命名为 operator <<

我得出的最接近的解决方案是通过创建一个中间类:

class Decorate {
    const A& a;
public:
    Decorate(const A& a_) : a(a_) {}
    friend std::ostream& operator<<(std::ostream& o, const PrintA& pa) {
        o << "This is A: " << pa.a;
        return o;
    }
};

并以这种方式打印它:

int main() {
    A a(0,42);
    std::cout << Decorate(a) << std::endl;
    return 0;
}

我一直在寻找更漂亮的东西,但根据 Angew 的回答,我失去了起诉正确operator<<声明的希望。

感谢您的帮助!将安格的回应标记为答案。