6

我有一个 c++ 库,它提供了一个具有复杂逻辑的对象。在数据处理期间,这个对象向 std::cout 输出很多东西(现在是硬编码的)。我希望处理输出不要转到标准输出,而是转到 custm 小部件(一些文本显示)。我试图创建一个std::ostream类成员,用一个参数设置它(std::cout 用于控制台应用程序和其他一些在 GUI 应用程序中处理的 ostream)。但是编译器向我抛出了以下错误:

[ 14%] 构建 CXX 对象 src/core/CMakeFiles/PietCore.dir/pvirtualmachine.cpp.o
/usr/include/c++/4.6/ostream:在构造函数'PVirtualMachine::PVirtualMachine(QString)'中:                                                                        
/usr/include/c++/4.6/ostream:363:7: 错误: 'std::basic_ostream::basic_ostream() [with _CharT = char, _Traits = std::char_traits]' 受保护
/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:33:50:错误:在此上下文中
在 /usr/include/c++/4.6/ios:45:0 包含的文件中,
                 来自 /usr/include/c++/4.6/ostream:40,
                 来自 /usr/include/c++/4.6/iterator:64,
                 来自/usr/include/qt4/QtCore/qlist.h:50,
                 来自/usr/include/qt4/QtCore/qvector.h:48,
                 来自/usr/include/qt4/QtGui/qpolygon.h:45,
                 来自 /usr/include/qt4/QtGui/qmatrix.h:45,
                 来自/usr/include/qt4/QtGui/qtransform.h:44,
                 来自/usr/include/qt4/QtGui/qimage.h:45,
                 来自/usr/include/qt4/QtGui/QImage:1,
                 来自/home/tomasz/Development/C++/piet/src/core/pcodepointer.h:17,
                 来自/home/tomasz/Development/C++/piet/src/core/pblockmanager.h:9,
                 来自/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.h:10,
                 来自/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:4:
/usr/include/c++/4.6/bits/ios_base.h:在成员函数'std::basic_ios& std::basic_ios::operator=(const std::basic_ios&)'中:
/usr/include/c++/4.6/bits/ios_base.h:791:5: 错误:'std::ios_base& std::ios_base::operator=(const std::ios_base&)' 是私有的
/usr/include/c++/4.6/bits/basic_ios.h:64:11:错误:在此上下文中
在 /usr/include/c++/4.6/iterator:64:0 包含的文件中,
                 来自/usr/include/qt4/QtCore/qlist.h:50,
                 来自/usr/include/qt4/QtCore/qvector.h:48,
                 来自/usr/include/qt4/QtGui/qpolygon.h:45,
                 来自 /usr/include/qt4/QtGui/qmatrix.h:45,
                 来自/usr/include/qt4/QtGui/qtransform.h:44,
                 来自/usr/include/qt4/QtGui/qimage.h:45,
                 来自/usr/include/qt4/QtGui/QImage:1,
                 来自/home/tomasz/Development/C++/piet/src/core/pcodepointer.h:17,
                 来自/home/tomasz/Development/C++/piet/src/core/pblockmanager.h:9,
                 来自/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.h:10,
                 来自/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:4:
/usr/include/c++/4.6/ostream:在成员函数'std::basic_ostream& std::basic_ostream::operator=(const std::basic_ostream&)'中:
/usr/include/c++/4.6/ostream:57:11: 注意:这里首先需要综合方法 'std::basic_ios& std::basic_ios::operator=(const std::basic_ios&)'
/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:在成员函数'void PVirtualMachine::setOutput(std::ostream)'中:
/home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:216:11:注意:合成方法'std::basic_ostream& std::basic_ostream::operator=(const std::basic_ostream&)'首先需要这里

如果有人指出我出了什么问题,我会很高兴,因为我不知道......

我的代码如下所示:

  • .h 文件
类 PVirtualMachine {
  私人的:
    std::ostream 输出;
    [...]
  上市:
    无效 setOutput(std::ostream);
    [...]
};
  • .cpp 文件
无效 PVirtualMachine::setOutput(std::ostream os)
{
  输出=操作系统;
}
4

3 回答 3

15

您在这里有两个选择:

  • 使用参考,或
  • 使用指针

您不能使用普通实例,因为ostream它是不可复制的。

使用引用(直接引用已经实例化的ostream

class PVirtualMachine {
  private:
    std::ostream & output;
    [...]
  public:
    PVirtualMachine(std::ostream &);  // Reference must be initialized on construction.
    [...]
};

好处:

  • 没有指针语法。
  • std::ostream只要不删除原始变量,就应该始终引用 的有效实例。

缺点:

  • 该类PVirtualMachine必须使用初始化列表中的输出引用来构造,否则将无法编译。
  • 初始化后无法更改引用。
  • 不能与移动赋值运算符一起使用(即operator=(PVirtualMachine &&)

使用指针(对对象的可选引用)

class PVirtualMachine {
  private:
    std::ostream * output;
    [...]
  public:
    void setOutput(std::ostream *);
    [...]
};

好处:

  • 可以实例化为空指针。
  • 可以轻松传递。
  • 可以更新以指向新std::ostream实例。
  • 可以在 PVirtualMachine 实例内部或外部创建。
  • 与移动赋值运算符一起使用。

缺点:

  • 指针语法。
  • 访问 ostream 和/或在构造函数中时必须检查空引用。
于 2013-01-27T01:11:24.387 回答
4

您可以使用对 a 的引用std::ostream,这将支持任何类型的输出流,例如标准输出、文件等。这很好,只要您只想使用一个流,并且流不会被破坏:

class PVirtualMachine {
  private:
    std::ostream & output;
    [...]
  public:
    PVirtualMachine(std::ostream & os = std::cout): output(os) { }
    // void setOutput(std::ostream & os) { output = os; } // can't change the reference
    [...]
};

如果您希望此类共享流(因此在此类的生命周期内使其保持活动状态),请使用 astd::shared_ptr<std::ostream>而不是引用。

于 2013-01-27T01:05:19.583 回答
0

我实际上会在我可能想要调试的模块中使用一个 ostream 实例。请注意,此类型没有默认构造函数,您必须将指针传递给流缓冲区,但该指针可以为空。现在,当/如果要捕获模块的输出时,只需使用rdbuf(). 这个流缓冲区可以是 std::cout 的流缓冲区,但它也可以是一个std::stringbufstd::filebuf一些自写的,自动将输出重定向到某个窗口。一个警告:没有流缓冲区的输出将设置故障位(甚至是坏位?),因此您必须clear()在更改流缓冲区后调用输出流。另请注意,您必须手动管理此流缓冲区和引用它的流的生命周期,不涉及所有权转移和自动清理。

于 2013-01-27T17:08:36.913 回答