友元函数及其与I/O操作符的关系

Friend functions and their relationship to the I/O Operators

本文关键字:操作符 关系 函数 友元      更新时间:2023-10-16

我仔细研究了有关好友功能及其使用的信息。它们能够访问类中封装的数据,同时不会违反OOP的黄金规则之一。在提供各种用于重载I/O操作符(一种基本操作,学习c++时最先教的操作之一)的源代码时,每个人都将操作符定义为友元,并在类外实现它。我的问题是:这个需要来完成吗?为什么不直接将函数声明为类的公共成员,并从类中插入/显示数据,同时保持所有内容的封装?这似乎与重载其他操作符没有什么不同,但它是一种被认为是重载I/O操作符的传统方法。

感谢您的宝贵时间。

假设你想为你的类X重载operator<<,那么你可以这样使用它:

X x;
std::cout << x;

注意std::cout是操作符的第一个操作数。要将其实现为成员函数,它必须是std::basic_ostream的成员,即std::cout的类型。不能向已定义的类添加成员。这就是为什么我们把它声明为一个自由函数。

如果您将operator<<重载为X的成员,则它将以X对象作为其第一个操作数,因此您可以这样使用它:

X x;
x << something;

这显然不是你在处理I/o时想要的。

如果像:a @ b这样的重载操作符实现为成员函数,则该调用将被转换为a.operator@(b);。这意味着函数必须是操作数类型的类的成员。在iostreams的情况下,这将是iostream本身成员所需的所有操作符。

虽然iostreams确实提供了一些插入/提取操作符作为成员,但您通常希望能够在不修改iostream类本身的情况下添加更多1。要做到这一点,您非常需要将操作符实现为自由函数,而不是成员函数。由于您通常仍然希望它能够访问您计划读/写(插入/提取,如果您喜欢)的任何类型的私有部分,因此它通常必须是该类的友元。


  1. 这是所谓的开/闭原则的一个例子:类应该对扩展开放,但对修改关闭。换句话说,您希望扩展它而不修改它。