将某些内容打印到 std::ostream 并返回 std::ostream 的函数?
-
23-08-2019 - |
题
我想编写一个函数,将一些内容输出到 ostream
传入的内容,并返回流,如下所示:
std::ostream& MyPrint(int val, std::ostream* out) {
*out << val;
return *out;
}
int main(int argc, char** argv){
std::cout << "Value: " << MyPrint(12, &std::cout) << std::endl;
return 0;
}
像这样打印值并将函数调用嵌入到输出运算符链中会很方便,就像我在 main()
.
然而它不起作用,并打印出以下内容:
$ ./a.out
12Value: 0x6013a8
所需的输出将是这样的:
Value: 12
我怎样才能解决这个问题?我必须定义一个 operator<<
反而?
更新: 澄清了期望的输出是什么。
更新2: 有些人不明白为什么我会使用函数来打印这样的数字,而不是直接打印它。这是一个简化的示例,实际上该函数打印一个复杂的对象而不是一个 int
.
解决方案
您不能修复功能。在规范概不要求编译器相对于在同一表达一些无关的运营商能够评估在任何特定的顺序在表达式中的函数调用。因此,在不改变调用代码,你不能让MyPrint()
std::cout << "Value: "
后评估
左到右的顺序的任务是对由多个连续<<运营商的表达式,因此,将工作。操作员的点<<返回流是,当运营商链的,每一个的LHS是由操作者的评价提供给它的左
您不能达到同样的事情有免费的函数调用,因为他们没有一个LHS。 MyPrint()
返回等于一个目的是std::cout
,也是如此std::cout << "Value: "
,所以你有效做std::cout << std::cout
,其被打印该十六进制值。
因为期望的输出是:
Value: 12
“正确”的事情确实是覆盖运营商<<。这通常意味着你需要要么使之成为朋友,或做这样的:
class WhateverItIsYouReallyWantToPrint {
public:
void print(ostream &out) const {
// do whatever
}
};
ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
obj.print(out);
}
如果你的类中重写operator<<
是不恰当的,例如,因为有多种格式,你可能想打印,并希望写一个不同的功能为每一个,那么应该放弃的念头操作者链接并调用函数,否则写把你的对象作为构造参数,各有不同的操作符重载多个类。
其他提示
您想使MyPrint一类朋友运算符<<:
class MyPrint
{
public:
MyPrint(int val) : val_(val) {}
friend std::ostream& operator<<(std::ostream& os, const MyPrint& mp)
{
os << mp.val_;
return os;
}
private:
int val_;
};
int main(int argc, char** argv)
{
std::cout << "Value: " << MyPrint(12) << std::endl;
return 0;
}
此方法需要你插入MyPrint对象插入所选择的流。如果你真的需要改变其流是活动的能力,你可以这样做:
class MyPrint
{
public:
MyPrint(int val, std::ostream& os) : val_(val), os_(os) {}
friend std::ostream& operator<<(std::ostream& dummy, const MyPrint& mp)
{
mp.os_ << mp.val_;
return os_;
}
private:
int val_;
std::ostream& os_
};
int main(int argc, char** argv)
{
std::cout << "Value: " << MyPrint(12, std::cout) << std::endl;
return 0;
}
你有两个选择。首先,使用您已有的:
std::cout << "Value: ";
MyPrint(12, &std::cout);
std::cout << std::endl;
另一种更像C++,是替换 MyPrint()
与适当的 std::ostream& operator<<
. 。已经有一个用于 int
, ,所以我会做一个稍微复杂一点的:
#include <iostream>
struct X {
int y;
};
// I'm not bothering passing X as a reference, because it's a
// small object
std::ostream& operator<<(std::ostream& os, const X x)
{
return os << x.y;
}
int main()
{
X x;
x.y = 5;
std::cout << x << std::endl;
}
有没有办法做你期待什么就有什么,因为功能在评估顺序的。
你有什么需要直接写这样的ostream的任何特别的原因吗?如果没有,只是有MyPrint返回一个字符串。如果你想使用内部MyPrint流生成输出,只需用strstream并返回结果。
首先,没有理由不在ostream
通过引用而不是由指针传递:
std::ostream& MyPrint(int val, std::ostream& out) {
out << val;
return out;
}
如果你真的不想使用std::ostream& operator<<(std::ostream& os, TYPE)
,你可以这样做:
int main(int argc, char** argv){
std::cout << "Value: ";
MyPrint(12, std::cout) << std::endl;
return 0;
}
改变指针到一个参考后,可以做到这一点:
#include <iostream>
std::ostream& MyPrint(int val, std::ostream& out) {
out << val;
return out;
}
int main(int, char**) {
MyPrint(11, std::cout << "Value: ") << std::endl;
return 0;
}
有MyPrint
的语法实质上是展开的operator<<
的但具有一个额外的参数。
在你的情况下,答案显然是:
std::cout << "Value: " << 12 << std::endl;
如果这还不够好,请解释一下你希望看到什么输出。