2

我们有一个基于带有自定义流缓冲区的 std::ostream 的日志实现。我们通过 Schwarz 计数器实现我们应用程序的日志类实例。

为了避免将较低级别的类耦合到我们的日志实现,我们可以传递对 std::ostream 的引用。通过这种方式,我们的低级类可以记录到 std::cout、std::cerr 或通过 Schwarz 计数器创建的实例。

我对此有一个问题。日志实现通过流运算符的重载设置其严重性:

// Overload the << operator to set the log message severity
inline CLogStream& operator << (CLogStream& myLogStream, eMsgType::type msgTypeCurrent)
{
  myLogStream.SetMsgTypeCurrent(msgTypeCurrent);
  return ( myLogStream ) ;
} 

这允许我们像这样使用记录器:

CLog::Main << CLog::MSG_FATAL << "Fatal error" << std::endl;

我想创建一个对我们应用程序的日志实例的引用,该日志被锁定到特定的严重性。这样,我可以将两个 std::ostream 引用传递给我们的实用程序类。其中一个用于正常报告,另一个用于错误报告。这些可以设置为 std::cout 和 std::cerr,或者设置为引用我们的日志对象实例的某种对象。

不幸的是,据我所知,std::ostream 运算符 << 不是虚拟的,所以我不确定如何设计这样的对象。

有什么想法吗?

4

3 回答 3

1

阅读有关ios_base::iword(). long它使您可以访问流对象中的值数组,您可以使用这些值来存储标志和特殊值等内容。

于 2013-02-12T13:13:57.870 回答
1

iostream具有虚拟成员函数(特别是~ios_base),因此您可以在dynamic_cast中执行 a operator<<

inline std::ostream &operator<<(std::ostream &os, eMsgType::type msgTypeCurrent) {
  if (CLogStream *myLogStream = dynamic_cast<CLogStream *>(&os)) {
    myLogStream->SetMsgTypeCurrent(msgTypeCurrent);
  } else {
    os << "TYPE: " << static_cast<typename std::underlying_type<eMsgType::type>
      ::type>(msgTypeCurrent) << ": ";
  }
  return os;
}
于 2013-02-12T10:50:59.880 回答
1

如果严重性的设置是持久的,那么这两行都会导致一个具有致命严重性的日志条目

CLog::Main << CLog::MSG_FATAL << "Log entry 1: " << some_data << std::endl;
CLog::Main << "Log entry 2: " << some_other_data << std::endl;

那么您的日志记录类已经被正确设计为作为通用传递ostream&。您只需要针对实用程序类支持的不同日志级别的单独记录器实例。

这是在假设记录器类已被继承ostream以利用现有operator<<重载的假设下编写的。在这种情况下,operator<<forsome_datasome_other_data已经完全不知道输出进入日志流。

于 2013-02-12T11:12:33.883 回答