Home Inheriting from a C++ class with no virtual functions

# Inheriting from a C++ class with no virtual functions

user9039
1#
user9039 Published in September 19, 2018, 3:17 am

We have a log implementation that's based on std::ostream with a custom stream buffer. We implement our application's instance of the log class via a Schwarz counter.

To avoid coupling our lower level classes to our log implementation, we can pass a reference to a std::ostream. In this way our lower level classes can log to std::cout, std::cerr or to the instance created via the Schwarz counter.

I have one problem with this. The log implementation sets its severity via an overload of the stream operator:

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


This allows us to use the logger like this:

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


I'd like to create a reference to our app's instance of the log which is locked to a particular severity. That way, I can pass our utility classes two std::ostream references. One of these would be used for normal reporting and the other for error reporting. These could be set to std::cout and std::cerr, or to some kind of object referring to our log object instance.

Unfortunately the std::ostream operator << aren't virtual as far as I'm aware, so I'm not sure how to design such an object.

Any thoughts?

• If SetMsgTypeCurrent is not virtual (i.e. CLogStream is not designed for inheritance) then tough. – Jon Feb 12 '13 at 10:37
• @Jon: I can change the definition of SetMsgTypeCurrent, so can make it virtual if that would help. But I need to access the class via std::ostream, so I don't see what options that would give me. The only virtual functions I'm aware of are down in std::streambuf, and none of them seem useful for this purpose. – Simon Elliott Feb 12 '13 at 10:52
• Not an answer, but: I can see other problems with this design as well. In particular, it's not thread-safe: Another thread could interfere between the << CLog::MSG_FATAL and the << "Fatal error". Is changing the design completely an option? – jogojapan Feb 12 '13 at 10:57
• @jogojapan: when the class was designed, threads were excluded from the app design. It's been suggested that we relax this constraint, so a design change is almost certainly in the pipeline. Another problem with this design is that the log messages are generated even if the log level is such that they don't get output. I think we can solve both of these problems together via some kind of wrapper, but that's a few months and a design review away. – Simon Elliott Feb 12 '13 at 11:06