簡體   English   中英

c++ Static 成員 function 記錄 class

[英]c++ Static member function in logging class

出於學習目的,我正在做 static class 進行日志記錄。 我有 function “startLog”,它刪除任何同名文件並打開文件進行寫入。 而且我有功能“日志”,它可以將一些文本打印到文件中並且它可以工作。 但是,當從“startLog”調用此 function 時,不會寫入文件。

log.log 文件中的預期結果:
[信息] 2022-07-29 20:04:07.?????? | log.cpp:34: 無效 startLog (const std::string&) | 日志打開... log.log
[調試] 2022-07-29 20:04:07.465570 | main.cpp:15: int main(int, char**) | 測試1 - 開始
[調試] 2022-07-29 20:04:08.547214 | main.cpp:22: int main(int, char**) | 測試1 - 結束

但是在運行它之后,log.log 文件中只有這個:
[調試] 2022-07-29 20:04:07.465570 | main.cpp:15: int main(int, char**) | 測試1 - 開始
[調試] 2022-07-29 20:04:08.547214 | main.cpp:22: int main(int, char**) | 測試1 - 結束

主文件

#include "log.hpp"

#include <iostream>

int main(int, char*[])
{
    std::string logFile {"log.log"};
    Log::startLog (logFile);
    Log::startLog ("log1.txt");
    int testCycles {100'000};


    Log::log ("TEST1 - START!", Log::DEBUG, logFile);

    for (int i = 0; i < testCycles; ++i)
    {
        Log::log("TEST" + std::to_string(i), Log::INFO, "log1.txt");
    }

    Log::log ("TEST1 - END!", Log::DEBUG, logFile);



    return EXIT_SUCCESS;

}

日志文件

#ifndef LOG_HPP
#define LOG_HPP

#include <fstream>
#include <source_location>
#include <string>
#include <string_view>

class Log
{
    public:
        enum
        {
            INFO,
            DEBUG,
            WARNING,
            ERROR,
            FATAL,
        };

        static void log                             (std::string_view errorMsg, int severity = Log::INFO, const std::string& logFile = s_logFile,
                                                                const std::source_location location = std::source_location::current());
        static void startLog                        (const std::string& logFile = "log.log");
        static std::string getLogFile               (){return s_logFile;};
        static void setLogLevel                     (int logLevel);

    private:
        static inline std::string                   s_logFile;
        static inline std::fstream                  s_outf {s_logFile, std::ios::app};
        static inline std::string                   s_logMsg [] = {"[INFO]", "[DEBUG]", "[WARNING]","[ERROR]", "[FATAL]"};
        static inline int                           s_logLevel = Log::INFO;
        Log                                         (){};


};

#endif // LOG_HPP_INCLUDED

日志文件

#include "log.hpp"
#include "utilities.hpp"

#include <filesystem>
#include <fstream>
#include <iomanip>
#include <string_view>

void Log::log                               (std::string_view errorMsg, int severity, const std::string& logFile, const std::source_location location)
{
    if (severity < Log::INFO)               severity = Log::INFO;
    else if (severity > Log::FATAL)         severity = Log::FATAL;
    if (severity < s_logLevel)              return;
    if (logFile != s_logFile)
    {
        s_outf.close();
        s_outf.open (logFile, std::ios::app);
        s_logFile = std::move (logFile);
    }
    s_outf
        << std::left << std::setw(10) << s_logMsg[severity]
        << Util::getTimeMillisec() << " | "
        << std::filesystem::path(location.file_name()).filename().string() << ":" << location.line() << ": " << location.function_name() << " | "
        << errorMsg <<'\n';

    // should be optimized in C++23 using location.resource_file to get filename instead of using std::filesystem

}

void Log::startLog                          (const std::string& logFile)
{
    s_logFile = logFile;
    remove (s_logFile.c_str());
    log ("Log opening ... " + s_logFile);
}

void Log::setLogLevel                       (int logLevel)
{
    if (logLevel < 0)                       s_logLevel = 0;
    else if (logLevel > Log::FATAL)         s_logLevel = Log::FATAL;
    else                                    s_logLevel = logLevel;
}

注意:有實用程序.hpp 和實用程序.cpp 來獲取格式化時間點,它工作正常,所以我在這里不包含代碼。

Log::startLog永遠不會導致日志文件被打開,因為s_logFile設置為log調用的默認參數。 最初也沒有打開文件,因為將空字符串傳遞給std::fstream的構造函數不會導致文件被打開。

你可能想要類似的東西

class Log
{
...
    static inline std::string                   s_logFile; // empty initially; will result in opening the file stream the first time a file name is passed to log
    static inline std::fstream                  s_outf; // not opened initially as before (opening file "" fails)
...
};
void Log::startLog(const std::string& logFile)
{
    remove(s_logFile.c_str());
    log("Log opening ... " + s_logFile, Log::INFO, logFile);
}

此外,您應該聽聽編譯器警告:

s_logFile = std::move(logFile);

你正在移動一個 const 左值引用。 您應該簡單地使用復制賦值運算符。

您的代碼甚至可以編譯嗎? 您在 Main function 中的 testCycles 初始化中有一個奇怪的錯字。 可能循環被稱為零次。 此外 static 意味着您的成員變量 s_logFile 是全局的。 你用兩個不同的參數調用它兩次。 我不認為它會做,你的意圖。

最后:谷歌關於 ifstream/ofstream。 如果使用得當,就不需要調用 open/close。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM