我有一个c ++库,它提供了一个具有复杂逻辑的对象。在数据处理期间,此对象向std :: cout输出大量内容(现在这是硬编码的)。我希望处理输出不是转到标准输出而是转到custm小部件(一些文本显示)。我尝试创建一个std::ostream
类成员,使用参数设置它(std :: cout用于控制台应用程序,其他一些ostream在GUI应用程序中处理)。但编译器会抛出以下错误:
[ 14%] Building CXX object src/core/CMakeFiles/PietCore.dir/pvirtualmachine.cpp.o /usr/include/c++/4.6/ostream: In constructor ‘PVirtualMachine::PVirtualMachine(QString)’: /usr/include/c++/4.6/ostream:363:7: error: ‘std::basic_ostream::basic_ostream() [with _CharT = char, _Traits = std::char_traits]’ is protected /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:33:50: error: within this context In file included from /usr/include/c++/4.6/ios:45:0, from /usr/include/c++/4.6/ostream:40, from /usr/include/c++/4.6/iterator:64, from /usr/include/qt4/QtCore/qlist.h:50, from /usr/include/qt4/QtCore/qvector.h:48, from /usr/include/qt4/QtGui/qpolygon.h:45, from /usr/include/qt4/QtGui/qmatrix.h:45, from /usr/include/qt4/QtGui/qtransform.h:44, from /usr/include/qt4/QtGui/qimage.h:45, from /usr/include/qt4/QtGui/QImage:1, from /home/tomasz/Development/C++/piet/src/core/pcodepointer.h:17, from /home/tomasz/Development/C++/piet/src/core/pblockmanager.h:9, from /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.h:10, from /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:4: /usr/include/c++/4.6/bits/ios_base.h: In member function ‘std::basic_ios& std::basic_ios::operator=(const std::basic_ios&)’: /usr/include/c++/4.6/bits/ios_base.h:791:5: error: ‘std::ios_base& std::ios_base::operator=(const std::ios_base&)’ is private /usr/include/c++/4.6/bits/basic_ios.h:64:11: error: within this context In file included from /usr/include/c++/4.6/iterator:64:0, from /usr/include/qt4/QtCore/qlist.h:50, from /usr/include/qt4/QtCore/qvector.h:48, from /usr/include/qt4/QtGui/qpolygon.h:45, from /usr/include/qt4/QtGui/qmatrix.h:45, from /usr/include/qt4/QtGui/qtransform.h:44, from /usr/include/qt4/QtGui/qimage.h:45, from /usr/include/qt4/QtGui/QImage:1, from /home/tomasz/Development/C++/piet/src/core/pcodepointer.h:17, from /home/tomasz/Development/C++/piet/src/core/pblockmanager.h:9, from /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.h:10, from /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:4: /usr/include/c++/4.6/ostream: In member function ‘std::basic_ostream& std::basic_ostream::operator=(const std::basic_ostream&)’: /usr/include/c++/4.6/ostream:57:11: note: synthesized method ‘std::basic_ios& std::basic_ios::operator=(const std::basic_ios&)’ first required here /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp: In member function ‘void PVirtualMachine::setOutput(std::ostream)’: /home/tomasz/Development/C++/piet/src/core/pvirtualmachine.cpp:216:11: note: synthesized method ‘std::basic_ostream& std::basic_ostream::operator=(const std::basic_ostream&)’ first required here
如果有人指出我出了什么问题,我会很高兴,因为我不知道......
我的代码如下所示:
class PVirtualMachine { private: std::ostream output; [...] public: void setOutput(std::ostream); [...] };
void PVirtualMachine::setOutput(std::ostream os) { output = os; }
答案 0 :(得分:12)
你有两个选择:
您无法使用普通实例,因为ostream
是不可复制的。
使用引用(直接引用已经实例化的ostream
)
class PVirtualMachine {
private:
std::ostream & output;
[...]
public:
PVirtualMachine(std::ostream &); // Reference must be initialized on construction.
[...]
};
优点:
缺点:
PVirtualMachine
类必须使用初始化列表中的输出引用构造,否则将无法编译。使用指针(对堆上对象的引用)
class PVirtualMachine {
private:
std::ostream * output;
[...]
public:
void setOutput(std::ostream *);
[...]
};
优点:
缺点:
答案 1 :(得分:4)
您可以使用对std::ostream
的引用,这将支持任何类型的输出流,例如stdout,file等。只要您只想使用一个流,并且流不会被破坏,这很好:
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
[...]
};
如果您希望此类共享流(因此在此类的生命周期内保持活动状态),请使用std::shared_ptr<std::ostream>
而不是引用。
答案 2 :(得分:0)
我实际上会在我可能要调试的模块中使用ostream实例。请注意,此类型没有默认构造函数,您必须将指针传递给streambuffer,但该指针可以为null。现在,当/如果要捕获模块的输出时,只需使用rdbuf()
将streambuffer附加到它上面。这个streambuffer可以是std :: cout的streambuffer,但它也可以是std::stringbuf
或std::filebuf
或一些自动编写的自动将输出重定向到某个窗口。需要注意的是:没有streambuffer的输出会设置failbit(甚至badbit?),因此在更改streambuffer后你必须在输出流上调用clear()
。另请注意,您必须手动管理此streambuffer的生命周期以及引用它的流,不涉及所有权转移和自动清理。