从没有虚拟函数的C++类继承

Inheriting from a C++ class with no virtual functions

本文关键字:C++ 继承 函数 虚拟      更新时间:2023-10-16

我们有一个基于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运算符<lt;据我所知,它们并不是虚拟的,所以我不知道如何设计这样一个对象。

有什么想法吗?

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

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

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

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

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

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

了解ios_base::iword()。它允许您访问流对象中的long值数组,您可以使用该数组存储标志和特殊值等内容。