15

我有一个工作记录器类,它将一些文本输出到一个富文本框(Win32,C++)。问题是,我总是这样使用它:

stringstream ss;  
ss << someInt << someString;  
debugLogger.log(ss.str());

相反,像流一样使用它会更方便,如下所示:

debugLogger << someInt << someString;

有没有比将所有内容转发到内部字符串流实例更好的方法?如果这样做,我什么时候需要冲洗?

4

5 回答 5

34

您需要operator <<为您的班级适当地实施。一般模式如下所示:

template <typename T>
logger& operator <<(logger& log, T const& value) {
    log.your_stringstream << value;
    return log;
}

请注意,这处理(非const)引用,因为该操作会修改您的记录器。另请注意,您需要返回log参数才能使链接起作用:

log << 1 << 2 << endl;
// is the same as:
((log << 1) << 2) << endl;

如果最里面的操作没有返回当前log实例,那么所有其他操作要么在编译时失败(错误的方法签名),要么在运行时被吞没。

于 2009-02-04T15:16:14.690 回答
16

重载插入运算符<< 不是要走的路。您必须为所有 endl 或任何其他用户定义的函数添加重载。

要走的路是定义你自己的streambuf,并将它绑定到一个流中。然后,您只需要使用流。

下面是几个简单的例子:

于 2009-02-04T17:09:31.047 回答
4

正如 Luc Hermitte 所指出的,有一篇“Logging In C++”文章描述了解决这个问题的非常巧妙的方法。简而言之,假设您具有以下功能:

void LogFunction(const std::string& str) {
    // write to socket, file, console, e.t.c
    std::cout << str << std::endl;
}

可以编写一个包装器以在 std::cout 中使用它,如下所示:

#include <sstream>
#include <functional>

#define LOG(loggingFuntion) \
    Log(loggingFuntion).GetStream()

class Log {
    using LogFunctionType = std::function<void(const std::string&)>;

public:
    explicit Log(LogFunctionType logFunction) : m_logFunction(std::move(logFunction)) { }
    std::ostringstream& GetStream() { return m_stringStream; }
    ~Log() { m_logFunction(m_stringStream.str()); }

private:
    std::ostringstream m_stringStream;
    LogFunctionType m_logFunction;
};

int main() {
    LOG(LogFunction) << "some string " << 5 << " smth";
}

在线演示

此外,斯图尔特提供了非常好的解决方案。

于 2018-01-27T12:10:34.087 回答
2

一个优雅的解决方案也解决了冲洗问题,如下所示:

#include <string>
#include <memory>
#include <sstream>
#include <iostream>

class Logger
{
    using Stream = std::ostringstream;
    using Buffer_p = std::unique_ptr<Stream, std::function<void(Stream*)>>;

public:
    void log(const std::string& cmd) {
        std::cout << "INFO: " << cmd << std::endl;
    }

    Buffer_p log() {
        return Buffer_p(new Stream, [&](Stream* st) {
            log(st->str());
        });
    }
};

#define LOG(instance) *(instance.log())

int main()
{
    Logger logger;
    LOG(logger) << "e.g. Log a number: " << 3;
    return 0;
}
于 2018-03-08T14:01:06.800 回答
-1

在 Logger 类中,覆盖 << 运算符。

单击此处了解如何实现 << 运算符。

您还可以使用面向方面的编程来避免代码中的日志记录语句。

于 2009-02-04T15:16:11.040 回答