很容易丢掉c ++调用

jav*_*red 8 c++

我正在尝试实现在不需要时不产生开销的日志记录(即根本不应该执行任何方法调用).我想要没有开销,因为它是低延迟代码.我刚刚添加#define ENABLE_LOGS到我的标题类中,现在它看起来像那样(你可以忽略细节)

#pragma once

#include <string>
#include <fstream>

#define ENABLE_LOGS

namespace fastNative {

    class Logger
    {
    public:
        Logger(std::string name_, std::string fileName, bool append = false);
        ~Logger(void);
        void Error(std::string message, ...);
        void Debug(std::string message, ...);
        void DebugConsole(std::string message, ...);
        void Flush();
        static Logger errorsLogger;
        static Logger infoLogger;
    private:
        FILE* logFile;
        bool debugEnabled;
    };

}
Run Code Online (Sandbox Code Playgroud)

每当我需要使用某种方法时,我应该像这样围绕它:

#ifdef ENABLE_LOGS
    logger.Debug("seq=%6d len=%4d", seq, length_);
#endif
Run Code Online (Sandbox Code Playgroud)

这是错误的错误(我可以忘记环绕)并使代码变脏.我能以某种方式修改我的代码而不是#ifdef每次都使用吗?

在C#中我喜欢Conditional我想我需要类似c ++的东西.

Too*_*one 13

首先,看看已经存在的东西是有意义的.这是一个常见问题,很多人以前都会解决它.例如,请参阅stackoverflow问题C++日志框架建议,以及Dobbs博士在C++中的高度可配置日志框架.

如果你自己动手,那么你应该从这里得到一些好主意.我过去使用过几种方法.一种是使条件本身有条件地定义

#ifdef ENABLE_LOGS
#define LOG(a,b,c) logger.Debug(a, b, c)
#else
#define LOG(a,b,c)
#endif
Run Code Online (Sandbox Code Playgroud)

另一种方法是有条件地定义日志记录类本身.非日志版本的所有内容都是空语句,您依赖于编译器优化所有内容.

#ifdef ENABLE_LOGS

class Logger
{
public:
    Logger(std::string name_, std::string fileName, bool append = false);
    ~Logger(void);
    void Error(std::string message, ...);
    void Debug(std::string message, ...);
    void DebugConsole(std::string message, ...);
    void Flush();
    static Logger errorsLogger;
    static Logger infoLogger;
private:
    FILE* logFile;
    bool debugEnabled;
};

#else

class Logger
{
public:
    Logger(std::string name_, std::string fileName, bool append = false) {}
    ~Logger(void) {}
    void Error(std::string message, ...) {}
    void Debug(std::string message, ...) {}
    void DebugConsole(std::string message, ...) {}
    void Flush() {}
};

#endif
Run Code Online (Sandbox Code Playgroud)

您可以将您的Logger实现放在ENABLE_LOGS宏控制下的cpp文件中.这种方法的一个问题是您希望确保定义接口,以便编译器可以优化所有内容.因此,例如,使用C字符串参数type(const char*).在任何情况下const std::string&都是优选的std::string(后者确保每次有呼叫时都有一个字符串副本).

最后,如果您采用第一种方法,则应该将所有内容封装起来,do() { ... } while(0)以确保在使用宏时可能不会出现奇怪的行为.


A. *_* K. 7

使用宏有一种方法(llvm的方式).

#ifdef ENABLE_LOGS
#define DEBUG(ARG) do { ARG; } while(0)
#else
#define DEBUG(ARG)
#endif
Run Code Online (Sandbox Code Playgroud)

然后用它作为:

DEBUG(logger.Debug("seq=%6d len=%4d", seq, length_););
Run Code Online (Sandbox Code Playgroud)

  • + @Monad:如果你想说'if(test)DEBUG(...); 别的......` 它使它成为一个单一的陈述.如果它扩展为`{ARG;}`,你会在`else`处得到语法错误. (3认同)