Output stream as class member

I have a C ++ library that provides an object with complex logic. During data processing, this object outputs a lot of things to std :: cout (this is now hardcoded). I would like the processing not to go to stdout, but to the custm widget (some text display). I tried to create an element of the class std::ostream

, set it with a parameter (std :: cout for a console app and some other thread processed inside the GUI app). But the compiler is throwing me the following errors:

[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

I would be glad if someone could point out to me what is wrong, because I have no idea ...

My code looks like this:

  • .h file
class PVirtualMachine {
  private:
    std :: ostream output;
    [...]
  public:
    void setOutput (std :: ostream);
    [...]
};
  • .cpp file
void PVirtualMachine :: setOutput (std :: ostream os)
{
  output = os;
}
+3


source to share


3 answers


You have two options:

  • Use links or
  • Use pointers

You cannot use regular instances because it is ostream

not copied.

Using links (direct link to already created ostream

)

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

      

Benefits:

  • Pointer syntax is missing.
  • No risk of memory leaks.

Disadvantages:



  • The link may become invalid if the original instance goes out of scope.
  • The class PVirtualMachine

    must be constructed with a reference to the output in the initialization list, otherwise it will not compile.
  • The link cannot be changed after it has been initialized.

Using pointers (reference to an object on the heap)

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

      

Benefits:

  • Can be created as a null pointer.
  • Easy to carry.
  • Can be created inside or outside a PVirtualMachine instance.

Disadvantages:



  • Pointer syntax.
  • The selection / deletion must be manually managed (unless you are using a smart pointer).
  • Should check for null references when accessing ostream.
+12


source


You can use a link to instead std::ostream

, this will support any output stream, eg. stdout, file, etc. This is fine if you only want to use one stream and the stream is not destroyed:

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
    [...]
};

      



If you want this class to stream (therefore keep it for this lifecycle) use std::shared_ptr<std::ostream>

instead of reference.

+4


source


I would use an instance of ostream in a module that I could debug. Note that there is no default constructor for this type, you need to pass a pointer to the streambuffer, but this pointer can be null. Now when / if you want to capture the output of a module, you simply attach a stream buffer to it with rdbuf()

. This streambuffer can be a std :: cout streambuffer, but it can also be std::stringbuf

either std::filebuf

or incorrectly written, which automatically redirects the output to some window. One caveat: exiting without streambuffer will set failbit (or even badbit?), So you must callclear()

in the output stream after changing the stream buffer. Also note that you have to manually manage the lifetime of this stream buffer and threads referencing it, there is no transfer of ownership and no automatic flushing.

0


source







All Articles