1

我正在寻找为不同严重程度的日志编写具有多个流的记录器:

class Logger{
public:
    std::ostream& errStream;
    std::ostream& warnStream;
}

这样我可以像这样使用流:

Logger L;
L.errStream << "This is an error message.";
L.warnStream << "This is a warning message.";

问题是,如何分别为每个流重载 operator<< ?这意味着我想根据写入的流采取不同的行动。

如果有帮助,我已经有 errWrite 和 warnWrite 的成员函数,它们以 std::string 作为参数:

void errWrite(std::string);
void warnWrite(std::string);

要使用这些,我会:

Logger L;
L.errWrite("This is an error message.");
L.warnWrite("This is a warning message.");

这些的问题在于它们没有替代 std::cout 和 std::cerr,我的代码已经填充了它们。我试图开发一些可以轻松放入现有代码的东西。所以最终我想要:

  1. 一种为不同成员分别重载运算符的方法。
  2. 我正在尝试做的另一种方法。

谢谢。

4

3 回答 3

2

要重载operator<<,类型需要不同。

因此,要做到这一点,您必须创建一个新类来替换std::ostream,例如owarnstreamand oerrstream

我认为这样的事情会起作用:

class oerrstream
{
 private:
   std::ostream& st;

 public:
   oerrstream(std::ostream &stream) : st(stream) {}
   std::ostream& getStream() { return st; };
};

然后你可以使用以下方法覆盖它:

oerrstream& operator<<(oerrstream &es, const std::string& s)
{
   es.getStream() << s;
   return es;
}

请记住,您将需要覆盖所有输出操作...使用模板可以做到这一点,如下所示:

template <typename T>
oerrstream& operator<<(oerrstream &es, T t)
{
   es.getStream() << t;
   return es;
}
于 2013-08-27T10:59:42.980 回答
1

您可以采用 IO 操纵器方法:

#include <iostream>
#include <string>

class Logger {
public:
    Logger()
        : errStream(std::cerr)
        , warnStream(std::cout)
        , active(&errStream)
    { }

    Logger& operator<<(const std::string& str)
    {
        *active << str;
        return *this;
    }

    Logger& operator<<(Logger&(*manip)(Logger&))
    {
        return manip(*this);
    }

private:
    std::ostream& errStream;
    std::ostream& warnStream;
    std::ostream* active;

    friend Logger& err(Logger&);
    friend Logger& warn(Logger&);
};

Logger& err(Logger& obj)
{
    obj.active = &obj.errStream;
    return obj;
}

Logger& warn(Logger& obj)
{
    obj.active = &obj.warnStream;
    return obj;
}

int main()
{
    Logger l;
    l << err << "error\n";
    l << warn << "warning\n";
}
于 2013-08-27T11:09:38.467 回答
0

这意味着我想根据写入的流采取不同的行动。

不确定“不同的动作”是什么意思,但这里有一个解释:

class Logger{
private:
    std::ostream& errStream;
    std::ostream& warnStream;

public:

    enum { err, warn } stream_type;


    std::ostream& get(stream_type const st)
    {
        // different actions per stream:
        switch(st)
        {
        case err:
            return errStream << "Error [" << gettime_function() << "] ";
        case warn:
            return warnStream << "Warning: ";
        }
    }
};

编辑:

如果您想专门化流本身,您可以轻松定义模板化输出运算符:

class ErrorStream
{
     std::ostream& underlying_;
public:
    ErrorStream(std::ostream& underlying) : underlying_(underlying) {}
    template<typename T> friend ErrorStream& operator << (
        ErrorStream& out, const T& arg)
    {
        // custom action for error stream goes here
        out.underlying_ << arg;
        return out;
    }
};

该运算符将适用于任何operator<< (std::ostream&, const T&)适用的T。

于 2013-08-27T11:05:41.717 回答