6

複雑なロジックを持つオブジェクトを提供する C++ ライブラリがあります。データ処理中、このオブジェクトは多くのものを std::cout に出力します (これは現在ハードコーディングされています)。処理出力を標準出力ではなく、customm ウィジェット (一部のテキスト表示) に出力したいと考えています。クラスメンバーを作成しようと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 出力;
    [...]
  公衆:
    void setOutput(std::ostream);
    [...]
};
  • .cpp ファイル
void PVirtualMachine::setOutput(std::ostream os)
{
  出力 = OS;
}
4

3 に答える 3

15

ここには 2 つのオプションがあります。

  • 参照を使用するか、
  • ポインターを使用する

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

利点:

  • null ポインターとしてインスタンス化できます。
  • 簡単に渡れます。
  • std::ostream新しいインスタンスを指すように更新できます。
  • PVirtualMachine インスタンスの内部または外部で作成できます。
  • 移動代入演算子で動作します。

短所:

  • ポインター構文。
  • ostream および/またはコンストラクターにアクセスするときは、null 参照をチェックする必要があります。
于 2013-01-27T01:11:24.387 に答える
4

代わりにa への参照を使用できますstd::ostream。これは、stdout、ファイルなど、あらゆる種類の出力ストリームをサポートします。これは、1 つのストリームのみを使用したい場合、およびストリームが破棄されない限り問題ありません。

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>は、参照の代わりに a を使用します。

于 2013-01-27T01:05:19.583 に答える
0

実際には、デバッグする可能性のあるモジュールで ostream インスタンスを使用します。この型にはデフォルトのコンストラクターがないことに注意してください。ストリームバッファーへのポインターを渡す必要がありますが、そのポインターは null にすることができます。モジュールの出力をキャプチャしたい場合は、 を使用してストリームバッファをアタッチするだけですrdbuf()。このストリーム バッファは、std::cout のストリーム バッファにすることができますが、出力を何らかのウィンドウに自動的にリダイレクトする自己作成のストリーム バッファにすることもできstd::stringbufます。std::filebuf1 つの注意点: ストリーム バッファを使用しない出力では、failbit (または badbit?) が設定されるため、ストリーム バッファclear()を変更した後に出力ストリームを呼び出す必要があります。また、このストリームバッファとそれを参照するストリームの有効期間を手動で管理する必要があることに注意してください。所有権の譲渡や自動クリーンアップは行われません。

于 2013-01-27T17:08:36.913 に答える