除了没有为它定义重载的 << 运算符外,它没有任何问题。<< 的现有重载需要一个带有签名ostream& (*fp)(ostream&)的操纵器。
如果你给它一个类型为ostream& (*fp)()的操纵器,你会得到一个编译器错误,因为它没有operator<<(ostream&, ostream& (*fp)())的定义。如果你想要这个功能,你必须重载 << 操作符来接受这种类型的操纵器。
您必须为此编写一个定义:
ostream& ostream::operator<<(ostream& (*m)())
请记住,这里没有发生任何神奇的事情。流库严重依赖标准C++ 特性:运算符重载、类和引用。
既然您知道如何创建您描述的功能,这就是我们不这样做的原因:
如果不传递对我们试图操作的流的引用,我们就不能对连接到最终设备的流(cin、out、err、fstream 等)进行修改。该函数(修饰符都是具有花哨名称的函数)要么必须返回一个与 << 运算符左侧无关的新 ostream,要么通过一些非常丑陋的机制,找出它应该使用哪个 ostream connect with else 修饰符右侧的所有内容都不会到达最终设备,而是发送到函数/修饰符返回的任何 ostream。
想想这样的流
cout << "something here" << tab << "something else"<< endl;
真正意思
(((cout << "something here") << tab ) << "something else" ) << endl);
其中每组括号对 cout 执行某些操作(写入、修改等),然后返回 cout 以便下一组括号可以对其进行处理。
如果您的制表符修饰符/函数没有引用 ostream,则必须以某种方式猜测 << 运算符左侧的 ostream 是什么才能执行其任务。您是否正在使用 cour、cerr、某些文件流……?除非以某种方式将信息传递给函数的内部,否则它们永远不会知道,为什么不知道如何像引用它一样简单。
现在要真正把重点放在家里,让我们看看endl到底是什么以及我们使用的 << 运算符的重载版本:
该运算符如下所示:
ostream& ostream::operator<<(ostream& (*m)(ostream&))
{
return (*m)(*this);
}
endl 看起来像这样:
ostream& endl(ostream& os)
{
os << '\n';
os.flush();
return os;
}
endl 的目的是添加换行符并刷新流,确保流的内部缓冲区的所有内容都已写入设备。为了做到这一点,它首先需要向这个流写入一个'\n'。然后它需要告诉流刷新。endl 知道要写入和刷新哪个流的唯一方法是让操作员在调用 endl 函数时将该信息传递给它。这就像我告诉你洗我的车,但从不告诉你在满员的停车场里哪辆车是我的。你永远无法完成你的工作。你需要我把我的车交给你,或者我可以自己洗。
我希望这能解决问题
PS - 如果你不小心发现了我的车,请把它洗干净。