欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++ Simple Message/Logging Class

程序员文章站 2022-07-02 15:57:48
在 Qt的源码与Protobuf 的代码中,看到相同的简单消息(日志)输出的类实现,基本思路是使用宏定义,重载临时类对象,调用类方法或者通过析构函数自动调用输出方法,实现消息输出。这里以 Protobuf 的LogMessage 类为例,简单描述实现方法。 类定义很简单,主要是构造函数、重载的 op ......

 

    在 qt的源码与protobuf 的代码中,看到相同的简单消息(日志)输出的类实现,基本思路是使用宏定义,重载临时类对象,调用类方法或者通过析构函数自动调用输出方法,实现消息输出。这里以 protobuf 的logmessage 类为例,简单描述实现方法。

    类定义很简单,主要是构造函数、重载的 operator<< 操作符、finish方法。构造函数传入日志等级、文件名及行号,为输出用。重载的 << 操作符为了流式输出。在后边实现了个私有的  finish 方法,该方法简单粗暴,就是调用输出函数,如果是 fatal 等级输出,还会抛出异常或者 abort。其定义如下:

enum loglevel {
  loglevel_info,     // informational.  this is never actually used by
                     // libprotobuf.
  loglevel_warning,  // warns about issues that, although not technically a
                     // problem now, could cause problems in the future.  for
                     // example, a // warning will be printed when parsing a
                     // message that is near the message size limit.
  loglevel_error,    // an error occurred which should never happen during
                     // normal use.
  loglevel_fatal,    // an error occurred from which the library cannot
                     // recover.  this usually indicates a programming error
                     // in the code which calls the library, especially when
                     // compiled in debug mode.
};

class libprotobuf_export logmessage {
 public:
  logmessage(loglevel level, const char* filename, int line);
  ~logmessage();

  logmessage& operator<<(const std::string& value);
  logmessage& operator<<(const char* value);
  logmessage& operator<<(char value);
  logmessage& operator<<(int value);
  logmessage& operator<<(uint value);
  logmessage& operator<<(long value);
  logmessage& operator<<(unsigned long value);
  logmessage& operator<<(long long value);
  logmessage& operator<<(unsigned long long value);
  logmessage& operator<<(double value);
  logmessage& operator<<(void* value);
  logmessage& operator<<(const stringpiece& value);
  logmessage& operator<<(const ::google::protobuf::util::status& status);
  logmessage& operator<<(const uint128& value);

 private:
  friend class logfinisher;
  void finish();

  loglevel level_;
  const char* filename_;
  int line_;
  std::string message_;
};

   

    同时实现了一个 logfinisher 类,只重载了 operator= 操作符,该方法只是调用 logmessage 的 finish 方法。

1 class libprotobuf_export logfinisher {
2  public:
3   void operator=(logmessage& other) {
4     other.finish();
5   }
6 };

 

    再者实现方便使用的宏定义,定义如下所示。主要为 google_log 宏,该宏构造 logmessage 临时对象,调用 logfinisher 的 operator= 方法,实现消息输出。在qt 的代码中,并没有实现类似  logfinisher 的类,直接构造了messagelog 临时对象,在对象析构时调用输出函数,临时对象生命周期会在构造完执行析构,执行消息输出。以下宏定义中还定义了 google_log_if ,即条件为 true 时,什么都不做 (void)0,为 false时调用 google_log。

 1 #define google_log(level)                                                 \
 2   ::google::protobuf::internal::logfinisher() =                           \
 3     ::google::protobuf::internal::logmessage(                             \
 4       ::google::protobuf::loglevel_##level, __file__, __line__)
 5 #define google_log_if(level, condition) \
 6   !(condition) ? (void)0 : google_log(level)
 7 
 8 #define google_check(expression) \
 9   google_log_if(fatal, !(expression)) << "check failed: " #expression ": "
10 #define google_check_ok(a) google_check(::google::protobuf::internal::isok(a))
11 #define google_check_eq(a, b) google_check((a) == (b))
12 #define google_check_ne(a, b) google_check((a) != (b))
13 #define google_check_lt(a, b) google_check((a) <  (b))
14 #define google_check_le(a, b) google_check((a) <= (b))
15 #define google_check_gt(a, b) google_check((a) >  (b))
16 #define google_check_ge(a, b) google_check((a) >= (b))

    

    通过以上实现,则可以在代码中使用以下形式进行消息输出或者断言。第一行直接输出 "hello sunshy",额,sunshy 是寡人姓名拼音的简拼,第二行在var0 和 var1 不相等时输出后边的消息,同时抛异常或者abort,相等时则 do nothing

1 google_log(info)<< "hello " <<"sunshy\n";
2 google_check_eq(var0, var1)<<" var0 not equal var\n";

 

    最新工作的事心有不畅,随便写写,以遣胸怀