9

ログファイルへの書き込みとログファイルへの書き込みのような独自のstd::coutオブジェクトを作成しましstd::coutた。

現在、ヘッダー ファイルでこのように定義していますが、未使用の変数の警告が表示されます。

ヘッダーファイル<MyLib/Log.h>

static LOut { };
static LOut lo;

template<typename T> inline LOut& operator<<(LOut& mLOut, const T& mValue)
{
    std::string str{toStr(mValue)};
    std::cout << str;
    getLogStream() << str;
    return mLOut;
}

使用法:

#include <MyLib/Log.h>
...
lo << "hello!" << std::endl;

すべきですlostatic?すべきですloextern

-like オブジェクトを宣言する正しい方法を説明しcout、主要な標準ライブラリの実装がどのようにそれを行うかを示してくれたことに感謝します。


編集: のcoutようなオブジェクトとは、対応するヘッダーを含めた後に常に使用できるグローバル変数を意味します。

4

5 に答える 5

7

std::coutは次のように簡単に宣言されます。

namespace std {
    extern ostream cout;
}

これは通常のグローバル変数です。自分でも同じことができます。変数のextern宣言をヘッダーに入れます。次に、ソース ファイルで同じ変数を定義し、それをアプリケーションにリンクします。

// mylog.h
extern MyLog mylog;

// mylog.cpp
MyLog mylog(someparams);
于 2013-07-21T18:35:20.457 に答える
1

まず、あなたが何を意味するのかよくわかりません のようcoutなオブジェクトですか? おそらくstd::ostream

とにかく、これを行う通常の方法は、フィルタリング streambuf を使用することです。通常の場所に加えて、ログ ファイルに転送する streambuf を書き、必要な場所に挿入します。

class LoggingOutputStreambuf : public std::streambuf
{
    std::streambuf* myDest;
    std::ofstreambuf myLogFile;
    std::ostream* myOwner;
protected:
    int overflow( int ch )
    {
        myLogFile.sputc( ch );  //  ignores errors...
        return myDest->sputc( ch );
    }
public:
    LoggingOutputStreambuf(
            std::streambuf* dest,
            std::string const& logfileName )
        : myDest( dest )
        , myLogFile( logfileName.c_str(), std::ios_base::out )
        , myOwner( nullptr )
    {
        if ( !myLogFile.is_open() ) {
            //  Some error handling...
        }
    }
    LoggingOutputStreambuf(
            std::ostream& dest,
            std::string const& logfileName )
        : LoggingOutputStreambuf( dest.rdbuf(), logfileName )
    {
        dest.rdbuf( this );
        myOwner = &dest;
    }
    ~LoggingOutputStreambuf()
    {
        if ( myOwner != nullptr ) {
            myOwner->rdbuf( myDest );
        }
    }
};

(これは C++11 ですが、C++03 用に変更するのは難しくありません。)

使用するには、次のようなものを使用できます。

LoggingOutputStreambuf logger( std::cout );
//   ...

へのすべての出力は、範囲外にstd::coutなるまでログに記録されます。logger

filebuf実際には、各行の先頭にタイム スタンプを挿入したり、各行の最後に体系的にフラッシュしたりしたい場合があるため、ロギングには よりも複雑なものを使用する可能性があります 。(ストリームバッファをフィルタリングすることで、これらの問題も解決できます。)

于 2013-07-21T16:52:15.060 に答える
0

私のプロジェクトの 1 つで、 のラッパーを書きましたstd::cout

次のようになります。

struct out_t {
    template<typename T>
    out_t&
    operator << (T&& x)  {
            std::cout << x;
            // log << x; 
            return *this;
    };
};

out_t out;

out << 1;

完全なコードについてstruct outは、io.h

于 2013-07-21T17:00:04.083 に答える