c++ - 轻松完全丢弃 c++ 调用

标签 c++

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

#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;
    };

}

每次我需要使用一些方法时,我应该像这样包围它:

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

它是错误提示器(我可能会忘记环绕)并使代码变脏。我能否以某种方式修复我的代码,使其不再每次都使用 #ifdef

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

最佳答案

首先,看看外面已经有什么是有意义的。这是一个常见问题,很多人以前都解决过。例如,参见 stackoverflow question C++ logging framework suggestions , 和 Dr Dobbs A Highly Configurable Logging Framework In C++ .

如果你自己动手,你应该从中得到一些好的想法。我过去使用过几种方法。一种是让语句本身有条件地定义

#ifdef ENABLE_LOGS
#define LOG(a,b,c) logger.Debug(a, b, c)
#else
#define LOG(a,b,c)
#endif

另一种方法是有条件地定义日志类本身。非日志版本将所有内容都作为空语句,您依赖编译器优化所有内容。

#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

您可以将 ENABLE_LOGSLogger 实现放在宏控制下的 cpp 文件中。这种方法的一个问题是您需要确保定义接口(interface),以便编译器可以优化所有内容。因此,例如,使用 C 字符串参数类型 (const char*)。在任何情况下,const std::string& 都优于 std::string(后者确保每次调用时都有一个字符串拷贝)。

最后,如果您选择第一种方法,则应将所有内容封装在 do() { ... } while(0) 中,以确保您在执行操作时不会出现奇怪的行为在可能需要复合语句的地方使用宏。

关于c++ - 轻松完全丢弃 c++ 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17663944/

相关文章:

c++ - 在 Cocoa 上创建后窗口消失

c++ - 如何并行运行 Cuda 内核调用和 CPU 函数?

c++ - 如何获得唯一指针列表?

c++ - 防止使用第三方基类

从 C++ 类调用 C# 方法

C++ 函数对象模板参数推导风格

c++ - 等价于 C++ 中来自 Java 的枚举的 .values()

.net - 合并两个图像,其中一个是透明的

c++ - 在静态断言和运行时错误之间自动选择

html - Visual Studio工具箱项不可用