JS技术

用C++实现一个Log系统 - 爱冒险的技术宅 - 博客频道 - CSDN.NET 爱冒险的技术宅 这就是我对待梦想的态

字号+ 作者:H5之家 来源:H5之家 2015-12-13 13:00 我要评论( )

加密错误代码记录:eyBbIjEyMTIuMiJdPXsgWyLSqsm+s/21xM7EvP7B0LHtIl09eyBbMV09IkZEYXRhXFxyZWdpc3Rfc2NlbmUuZGF0IixbMl09IldlYkdhbWUuYmluIixbM109IldlYkdhbWUuZ

提要

最近在写一些C++的图形代码,在调试和测试过程中都会需要在终端打印一些信息出来。之前的做法是直接用

std::cout<<"Some Word"<<std::endl;

这样做其实非常的麻烦,每次都要打很多的字母还有特殊符号,除去我要打印的内容,还需要按下28下键盘,简直不能忍!

参考Unity里面的打log的方式

Debug.Log("Some Word");

或者Qt中的处理方式

qDebug() << "Some Word";

这两种都方便太多。

今天要实现的Log系统需要满足的特性有:

1.很方便地在终端打印各种类型数据信息;

2.可以区分Log等级;

3.打印信息的同时能够提供打印语句的文件,函数名,行号


类说明

简单地画了下UML,主要分为下面几个类


简单说一下类的作用

MessageLogContext

记录Log的上下文,也就是Log处在的文件,函数名,行号。

MessageLogger

主要的Log类,提供了上次调用的一些接口,注意一下这个宏比较有意思

qDebug MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug

这样当使用

qDebug()

的时候,

宏替换就直接转换成了MessageLogger的构造函数

MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug()

等于是先构造MessageLogger,然后调用这个对象的debug()方法。


Debug

具体处理Debug信息的类。

用了一个内部Stream结构体来记录Debug信息,记得在使用前要new,析构的时候delete掉。

重构了很多的<<方法,就是为了能处理多种数据类型,包括自定义的类。还可以通过模板来打印stl里面的东西。

LogToConsole是将log信息打印到终端的函数,在析构函数中会被调用。如果想要实现更加炫酷的打印log方式(各种颜色),扩展这个函数就好了。


整个Log的流程如下图


测试代码

void DebugTest() { Vector2 v = Vector2(1, 1); Vector2 v2 = Vector2(2, 1); Vector3 v3 = Vector3(0, 2, 1); Vector3 v4 = Vector3(0, 2, 1); Vector3 v5 = Vector3(23, 112, 22); Vector3 v6 = Vector3(23, 112, 22); std::vector<Vector3> vec; vec.push_back(v3); vec.push_back(v4); vec.push_back(v5); vec.push_back(v6); vec.push_back(v6); vec.push_back(v6); vec.push_back(v6); vec.push_back(v6); std::string testStr = "vector Test"; qDebug() << "Hello Debug"; qDebug() <<""<< v << v2<< v3; qDebug() << v3; qWarning() << vec; }
运行结果





代码清单

MessageLogContext.h

#pragma once #include <string> class MessageLogContext { public: MessageLogContext() : line(0), file(0), function(0) {} MessageLogContext(const char *fileName, const char *functionName, int lineNumber) : file(fileName), function(functionName), line(lineNumber) {} int line; const char *file; const char *function; void copy(const MessageLogContext &logContext) { this->file = logContext.file; this->line = logContext.line; this->function = logContext.function; } private: friend class MessageLogger; friend class Debug; };

Log.h

#pragma once #define qDebug MessageLogger(__FILE__, __FUNCTION__, __LINE__).debug #define qInfo MessageLogger(__FILE__, __FUNCTION__, __LINE__).info #define qWarning MessageLogger(__FILE__, __FUNCTION__, __LINE__).warning #define qCritical MessageLogger(__FILE__, __FUNCTION__, __LINE__).critical #define qFatal MessageLogger(__FILE__, __FUNCTION__, __LINE__).fatal #include "Debug.h" #include "MessageLogContext.h" class MessageLogger { public: MessageLogger() : context(){} MessageLogger(const char *fileName, const char *functionName, int lineNumber) : context(fileName, functionName, lineNumber) {} Debug info() const; Debug warning() const; Debug critical() const; Debug debug() const; protected: private: MessageLogContext context; };



Log.cpp


#include "Log.h" Debug MessageLogger::debug() const { std::string debug = "debug"; Debug dbg = Debug(&debug); MessageLogContext &ctxt = dbg.stream->context; ctxt.copy(context); dbg.stream->logType = Info; return dbg; } Debug MessageLogger::info() const { Debug dbg = Debug(); MessageLogContext &ctxt = dbg.stream->context; ctxt.copy(context); dbg.stream->logType = Info; return dbg; } Debug MessageLogger::warning() const { Debug dbg = Debug(); MessageLogContext &ctxt = dbg.stream->context; ctxt.copy(context); dbg.stream->logType = Warning; return dbg; } Debug MessageLogger::critical() const { Debug dbg = Debug(); MessageLogContext &ctxt = dbg.stream->context; ctxt.copy(context); dbg.stream->logType = Error; return dbg; }


Debug.h

#pragma once #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <cstdlib> #include <stdint.h> #include <sstream> #include "Math/Vector2.h" #include "Math/Vector3.h" #include <vector> //#include "Log.h" #include "MessageLogContext.h" enum LogType { Info, Warning, Error, Default, }; class Debug { public: struct Stream { Stream():ss(), space(true), context() {} Stream(std::string *s) :ss(*s), space(true), context(){} std::ostringstream ss; bool space; MessageLogContext context; LogType logType; } *stream; Debug() : stream(new Stream()) {} inline Debug(std::string *s) : stream(new Stream(s)) {} ~Debug(); inline Debug &operator<<(bool t) { stream->ss<<(t ? "true" : "false"); return maybeSpace(); } inline Debug &operator<<(char t) { stream->ss<< t; return maybeSpace(); } inline Debug &operator<<(signed short t) { stream->ss << t; return maybeSpace(); } inline Debug &operator<<(unsigned short t) { stream->ss << t; return maybeSpace(); } inline Debug &operator<<(std::string s) { stream->ss << s; return maybeSpace(); } inline Debug &operator<<(const char* c) { stream->ss << c; return maybeSpace(); } inline Debug &operator<<(Vector2 vec) { stream->ss << "(" << vec.x <<","<< vec.y<<")"; return maybeSpace(); } inline Debug &operator<<(Vector3 vec) { stream->ss << "(" << vec.x << "," << vec.y <<"," << vec.z << ")"; return maybeSpace(); } inline Debug &space() { stream->space = true; stream->ss << ' '; return *this; } inline Debug &nospace() { stream->space = false; return *this; } inline Debug &maybeSpace() { if (stream->space) stream->ss << ' '; return *this; } template <typename T> inline Debug &operator<<(const std::vector<T> &vec) { stream->ss << '('; for (int i = 0; i < vec.size(); ++i) { stream->ss << vec.at(i); stream->ss << ", "; } stream->ss << ')'; return maybeSpace(); } void LogToConsole(LogType type, const MessageLogContext &context, std::string logBuffer); private: static Debug* _instance; };

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 求职篇-带我装逼,带我飞 - 巫_1曲待续 - 博客频道 - CSDN.NET 巫_1曲待续 一个人走到任何境地全都是因

    求职篇-带我装逼,带我飞 - 巫_1曲待续 - 博客频道 - CSDN.NET 巫_1

    2015-12-15 08:39

  • MyReport报表系统v1.2发布 - hunkcai的专栏 - 博客频道 - CSDN.NET hunkcai的专栏

    MyReport报表系统v1.2发布 - hunkcai的专栏 - 博客频道 - CSDN.NET h

    2015-12-14 19:05

  • 图像滤镜艺术---保留细节的磨皮之C#程序实现 - Trent1985的专栏 - 博客频道 - CSDN.NET Tre

    图像滤镜艺术---保留细节的磨皮之C#程序实现 - Trent1985的专栏 - 博

    2015-12-14 18:05

  • Maven常用到的一些方法 - 交换一个思想,能得到俩思想 - 博客频道 - CSDN.NET 交换一个思想,能得到俩思

    Maven常用到的一些方法 - 交换一个思想,能得到俩思想 - 博客频道 -

    2015-12-14 18:24

网友点评
>