c++ 将某些内容打印到std::ostream并返回std::ostream?

tzxcd3kk  于 2023-08-09  发布在  其他
关注(0)|答案(8)|浏览(126)

我想写一个函数,输出一些东西到传入的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<<吗?

**更新:**阐明了所需的输出。
**UPDATE2:**有些人不明白为什么我会打印这样的数字,使用函数而不是直接打印。这是一个简化的示例,实际上该函数打印的是一个复杂的对象,而不是int

igsr9ssn

igsr9ssn1#

你不能修复这个功能。规范中没有任何内容要求编译器以任何特定的顺序对表达式中的函数调用进行求值,该顺序与同一表达式中的一些不相关的操作符有关。因此,在不更改调用代码的情况下,不能使MyPrint()std::cout << "Value: "之后求值
对于由多个连续<<运算符组成的表达式,强制要求从左到右的顺序,因此这将起作用。operator<<返回流的要点是,当操作符被链接时,每个操作符的LHS由其左边的操作符的求值提供。
你不能用自由函数调用实现同样的事情,因为它们没有LHS。MyPrint()返回一个等于std::cout的对象,std::cout << "Value: "也是如此,所以实际上是在执行std::cout << std::cout,即打印十六进制值。
因为期望的输出是:

Value: 12

字符串
“正确”的做法确实是覆盖operator<<。这通常意味着你需要让它成为朋友,或者这样做:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}


如果为你的类重写operator<<并不合适,例如,因为你可能想要打印多种格式,并且你想为每种格式编写不同的函数,那么你要么给予操作符链接的想法,只调用函数,要么编写多个类,将你的对象作为构造函数参数,每个类都有不同的操作符重载。

2uluyalo

2uluyalo2#

你想让MyPrint成为一个带有friend operator<<的类:

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;
}

lx0bsm1f

lx0bsm1f3#

你有两个选择。第一,使用你已经拥有的东西:

std::cout << "Value: ";
MyPrint(12, &std::cout);
std::cout << std::endl;

字符串
另一个更像C++的方法是用适当的std::ostream& operator<<替换MyPrint()。已经有一个针对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;
}

pexxcrt2

pexxcrt24#

由于函数的求值顺序,无法在那里执行您所期望的操作。
有什么特别的原因需要像那样直接写入ostream吗?如果没有,只需让MyPrint返回一个字符串。如果您想在MyPrint中使用流来生成输出,只需使用strstream并返回结果。

e0bqpujr

e0bqpujr5#

首先,没有理由不通过引用而不是通过指针传入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;
}

wz3gfoph

wz3gfoph6#

将指针更改为引用后,可以执行以下操作:

#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<<,但有一个额外的参数。

r1wp621o

r1wp621o7#

这个问题可以这样解决:


的数据

vq8itlhq

vq8itlhq8#

在你的情况下,答案显然是:

std::cout << "Value: " << 12 << std::endl;

字符串
如果这还不够好,请解释您希望看到的输出。

相关问题