将内容输出到std :: ostream并返回std :: ostream的函数?

时间:2009-07-06 16:28:44

标签: c++ outputstream ostream

我想编写一个函数,输出传递给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

7 个答案:

答案 0 :(得分:11)

您无法修复此功能。规范中没有任何内容要求编译器针对同一表达式中某些不相关的运算符以任何特定顺序计算表达式中的函数调用。因此,在不更改调用代码的情况下,您无法在MyPrint()

之后进行std::cout << "Value: "评估

从由多个连续&lt;&lt;&lt;&lt;&lt;运营商,这样才行。运算符的点&lt;&lt;返回流是当运算符被链接时,每个运算符的LHS由运算符左侧的评估提供。

自由函数调用无法实现相同的功能,因为它们没有LHS。 MyPrint()会返回一个等于std::cout的对象,std::cout << "Value: "也是如此,因此您正在有效地执行std::cout << std::cout,即打印该十六进制值。

由于所需的输出是:

Value: 12

“正确”的事情确实要覆盖运算符&lt;&lt;。这通常意味着你需要把它变成朋友,或者这样做:

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

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

如果您的班级覆盖operator<<不合适,例如因为您可能想要打印多种格式,并且您想为每个格式编写不同的函数,那么您应该放弃关于运算符链接的想法,只需调用函数,或者编写多个类,将对象作为构造函数参数,每个类都有不同的运算符重载。

答案 1 :(得分:6)

您希望MyPrint与朋友运营商&lt;&lt;:

一起成为一个班级
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;
}

答案 2 :(得分:4)

您有两种选择。第一个,使用你已经拥有的是:

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

答案 3 :(得分:1)

由于评估函数的顺序,没有办法做你期望的事。

你有什么特别的理由需要直接写给ostream吗?如果没有,只需让MyPrint返回一个字符串。如果要在MyPrint中使用流来生成输出,只需使用strstream并返回结果。

答案 4 :(得分:0)

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

答案 5 :(得分: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<<的语法,但带有额外的参数。

答案 6 :(得分:-1)

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

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

如果这还不够好,请说明您想要看到的输出。