6

我想创建一个记录器类,它的功能如下:

Logger log;
log << "Error: " << value << "seen" << endl;

这应该给我打印一条自定义格式的消息。例如“12-09-2009 11:22:33 看到错误 5”

我的简单类目前看起来像这样:

class Logger {
    private:
        ostringstream oss;
    public:
        template <typename T>
        Logger& operator<<(T a);
}

template <typename T>
Logger& Logger::operator<<(T a) {
    oss << a;
    return *this;
}

void functionTest(void) {
    Logger log;
    log << "Error: " << 5 << " seen";
}

这将导致 oss 正确地拥有缓冲区“错误:5 看到”。但我不知道我需要编写/修改什么其他功能才能在屏幕上打印一些东西。有谁知道如何让它工作,或者有没有另一种方法来设计这个类来让我的功能工作?

4

5 回答 5

4

每个后面都有std::ostream一个streambuf。它可以通过 检索和设置std::stream::rdbuf()。特别是,它可以被包装——您可以提供一个对流式文本进行后处理的 streambuf 对象。(后处理意味着你无法std::cout << 123;区分std::cout << "123";

在您的特定情况下,后处理相当简单。在每一行的开头你要插入一些字节。这仅仅意味着您应该跟踪您是否已经输出了当前行的前缀。如果没有,请这样做并设置标志。每当您看到换行符时,请重置它。您的 streambuf 包装器只有一个bool值的状态。

于 2010-02-10T09:49:57.340 回答
1

据我所知,您的记录器与 ostringstream 没有什么不同。它只接受给定的内容并将其输出到字符串流。如果你想像这样使用它,你可以为 Logger 编写一个析构函数,它将字符串输出到 cout。

Logger::~Logger()
{
    std::cout<<getcurrentDateTimeAsString()<<" "<<oss.str()<<std::endl;
}

但当然,如果在整个程序中创建和使用 Logger*,这将毫无意义。

于 2010-02-10T09:15:40.533 回答
1

问题是选择何时以及如何逐行同步信息?所以无论是否缓冲,都只能控制EOL和线路上的信息——刷新或直接输出。

即使将析构函数用作 EOL/Flush,

{ log << [anything]; }作为 inline-local 堆栈括号语法来调用退出括号的 log 的析构函数,或者作为 std::endl,都必须使用。

除非使用诸如 '<<' 或 "+' 之类的附加运算符来实现元对象,否则您一直有义务使用显式方式来结束行和/或刷新。

于 2015-01-23T20:02:38.177 回答
1

查看编译时优化中提出的简单记录器- 从发布二进制文件中删除调试打印。应该足以满足您的需求。兄弟,格拉詹

于 2013-02-06T18:17:16.540 回答
0

这(来自这篇文章)做了你想要的,但它迫使你用 std::endl 结束每一行:

class Logger {
    private:
        ostringstream oss;
    public:
        template <typename T>
        Logger& operator<<(T a);

    Logger& operator<<( std::ostream&(*f)(std::ostream&) )
    {
        if( f == std::endl )
        {
            std::cout << "12-09-2009 11:22:33" << oss.str() << std::endl;   
            oss.str("");
        }
        return *this;
    }
};

template <typename T>
Logger& Logger::operator<<(T a) {
    oss << a;
    return *this;
}

void functionTest(void) {
    Logger log;
    log << "Error: " << 5 << " seen" << std::endl;
}

int main()
{
    functionTest();
}

编辑:好吧,根据您的评论,这似乎不是您想要的。然后我建议你按照 MSalters 所说的那样做。

于 2010-02-10T09:19:48.187 回答