重载operator< & lt;作为会员打印

Overloading operator<< for printing as a member

本文关键字:打印 lt operator 重载      更新时间:2023-10-16

有没有办法重载<<操作符,作为类成员,将值打印为文本流。如:

class TestClass {
public:
    ostream& operator<<(ostream& os) {
        return os << "I'm in the class, msg=" << msg << endl;
    }
private:
    string msg;
};

int main(int argc, char** argv) {
    TestClass obj = TestClass();
    cout << obj;
    return 0;
}

我能想到的唯一方法是在类外重载操作符:

ostream& operator<<(ostream& os, TestClass& obj) {
    return os << "I'm outside of the class and can't access msg" << endl;
}

但是,访问对象的私有部分的唯一方法是将操作符函数设为友,如果可能的话,我宁愿避免设为友,因此请您提供其他解决方案。

任何关于如何进行的评论或建议都将有所帮助:)

必须是非成员,因为该类构成操作符的第二个实参,而不是第一个实参。如果只能使用公共接口完成输出,那么就完成了。如果它需要访问非公共成员,那么你就必须将它声明为好友;这就是朋友该做的。

class TestClass {
public:
    friend ostream& operator<<(ostream& os, TestClass const & tc) {
        return os << "I'm a friend of the class, msg=" << tc.msg << endl;
    }
private:
    string msg;
};

您偶然发现了实现此功能的规范方法。

我认为一种流行的方法是使用非成员、非友元的operator<<调用类中的公共非虚拟print方法。这个打印方法既可以完成工作,也可以委托给受保护的虚拟实现。

class TestClass {
public:
    ostream& print(ostream& os) const {
        return os << "I'm in the class, msg=" << msg << endl;
    }
private:
    string msg;
};

ostream& operator<<(ostream& os, TestClass& obj) {
    return obj.print(os);
}
int main(int argc, char** argv) {
    TestClass obj;
    cout << obj;
    return 0;
}

您可以使它成为类的成员,即在<<的左侧,在您的示例中是ostream

你能做的,不过,是有一个基类与void do_stream(ostream& o);成员所有的流和非成员operator<<将调用它。

你是对的,这是实现流操作符的唯一方法——在类之外。

您需要将方法声明为friend

您必须将其设置为非成员(因为第一个参数不是您的类)。

但是你可以把它写在你的类定义中(作为友元):

class TestClass
{
public:
    // Have a nice friend.
    // This tightly binds this operator to the class.
    // But that is not a problem as in reality it is already tightly bound.
    friend ostream& operator<<(ostream& os, TestClass const& data)
    {
        return os << "I'm in the class, msg=" << data.msg << endl;
    }
private:
    string msg;
};

我觉得和这个做朋友没什么不好。