7

C++ でログ クラスを作成しています。このクラスはシングルトンです。このような方法でログを追加したい:

Log::GetInstance() << "Error: " << err_code << ", in class foo";

わかりました、そして Log オブジェクト内で、最後の引数が来た時点でこの行全体を保存したいと思います (この例では ", in class foo")。

最後の << 引数を検出するには? << a << b << is_this_last << Maybe_this_is << or_not.

終了タグは使用しません。

4

7 に答える 7

18

この問題は、シングルトンを使用しないことで解決できます。次のような関数を作成する場合:

Log log()
{
    return Log();
}

以前とほぼ同じ方法でログを追加できます。

log() << "Error: " << err_code << ", in class foo";

違いは、Logオブジェクトのデストラクタがこの行の後に呼び出されることです。これで、最後の引数がいつ処理されたかを検出する方法ができました。

于 2010-08-16T20:53:10.460 に答える
9

Log::GetInstanceログ オブジェクト自体ではなく、プロキシ オブジェクトを返してもらいます。プロキシ オブジェクトは、書き込まれたデータを保存し、そのデストラクタで、蓄積されたデータを実際にログに書き込みます。

于 2010-08-16T20:55:10.987 に答える
5

演算子 << の後に Log が別のオブジェクトを返すようにします。

template<typename T>
LogFindT operator<<(Log aLog, T const& data)
{
    // Put stuff in log.
    log.putStuffInLog(data);

    // now return the object to detect the end of the statement.
    return LogFindT(aLog);
}


struct LogFindT
{
    LogFindT(Log& aLog) : TheLog(aLog) {}
    Log& TheLog;
    ~LogFindT()
    {
        // Do stuff when this object is eventually destroyed
        // at the end of the expression.
    }
};

template<typename T>
LogFindT& operator<<(LogFindT& aLog, T const& data)
{
     aLog.TheLog.putStuffInLog(data);

     // Return a reference to the input so we can chain.
     // The object is thus not destroyed until the end of the stream.
     return aLog;
}
于 2010-08-16T21:00:45.173 に答える
4

Jerry と Martin が最良の提案をしたと思いますが、完全を期すために、私が最初に考えたのはstd::endl.

カスタム クラスによってシステムLog内に実装した場合は、行末にorを追加するだけです。あなたが尋ねているので、私はあなたがしなかったと思います。iostreamstreambuf<< endl<< flush

しかし、仕組みを真似ることはできますendl。マニピュレータ ハンドラを追加するか、

Log &operator<< ( Log &l, Log & (*manip)( Log & ) )
    { return manip( l ); } // generically call any manipulator

Log &flog( Log &l ) // define a manipulator "flush log"
    { l->flush(); return l; }

または専用の追加operator<<

struct Flog {} flog;

Log &operator<< ( Log &l, Flog )
    { l->flush(); return l; }
于 2010-08-16T21:24:17.983 に答える
1

オペレーターを賢くしすぎないでください。意味がある場合は、演算子をオーバーロードする必要があります。ここではすべきではありません。それは奇妙に見えます。

次のような静的メソッドが必要です。

Log::Message( message_here );

std::stringを取ります。次に、クライアントはエラー文字列を組み立てる方法を理解するという頭痛の種を抱えています。

于 2010-08-16T20:58:00.853 に答える
0

あなたが望むことをする良い方法はありません。C と C++ は単純に行指向の言語ではありません。「コード行」などの大きな単位はなく、連鎖呼び出しも結合されていません。

C++ では、式 "a << b << c << d" は、次のように operator<< を 3 回個別に呼び出すこととまったく同じです。

 t1 = a;
 t2 = t1.operator<<(b);
 t3 = t2.operator<<(c);
 t4 = t3.operator<<(d);

これが、C++ ostream が明示的な行末マーカーとして endl を使用する理由です。それ以外の場合は、まともな方法はありません。

于 2010-08-16T21:46:47.987 に答える