【标准c++】日志如何设计和实现?

windyJ 2001-12-30 11:33:20
【标准c++】假如一个面向对象的系统,需要在每个类里增加日志功能,假设每个对象在运行自己方法的时候要记录一些信息到一个日志文件;怎么实现?
1:写一个全局函数,参数是信息(例如string);然后在整个类体系的基类实现一个方法,调用这个函数,而派生类可以继承基类的方法。
2:想把记入日志的功能委托给一个单独的类来做,例如:InfoLog类;这时,怎样在类体系中初始化这个类的对象?
写在构造函数里?那么每个派生类都要在构造函数里暴露基类的接口,说不定还要把InfoLog的构造参数(例如文件名)也暴露出来,满天飞?
用setInfoLog()打补丁?很难控制,容易出错,会出现忘了初始化的情况;

大家在开发过程中是怎么处理这个问题,如果有类似的经验,请不防指点一二~!

先谢谢啦!
...全文
906 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
fixopen 2002-01-23
  • 打赏
  • 举报
回复
我觉得日志是有一定格式的,可以先形成一个LogItem结构,其中存放日志内容,写一个类,如:LogManager,其中提供几个动态方法,如:WriteLog(LogItem li)等等。
直接LogManager::WriteLog(builderLogItem(now, who, what, where, ...))就行了
builderLogItem构造一个LogItem,当然,你可以用LogItem的构造函数:)
windyJ 2002-01-23
  • 打赏
  • 举报
回复
refresh
thank you, alou, gigix ,sealcecily
windyJ 2002-01-07
  • 打赏
  • 举报
回复
解决:

仍然采用单类继承的类体系结构,在类体系结构里提供统一的接口来记录日志;然后,用一个日志类来实现具体的日志记录;然后用一个跟日志类体系(日志类可能会派生出子类)并行的辅助类将日志类的初始化包装起来,并提供辅助类的无参数构造函数接口。

在其他类的统一基类的构造函数里,调用辅助类的构造函数,初始化日志类;然后在类体系结构的统一接口(方法)里,调用日志类的方法来实现日志记录。这样的话,所有对日志类的引用接口从基类继承而来,无需重新配置或实现,也有较好的一致性。而对日志类所有的初始化工作,将固化在辅助类里,如果以后需要的日志类对象不同,或日志类提供的接口改变,需要修改的,就是这个辅助类了。

其他类仍然可以重新实现体系的统一接口,从而一个系统里可以使用多种记录日志的方法;如果需要记录多个日志,还可以将这些日志类的初始化都用辅助类管理起来。

大家尤其是资深的c++程序员会担心,从一个基类继承会不会有问题,其实,从一般系统的情况,是可以这样做的。

这样做,还可以避免使用全局函数或全局变量;实际上,用一个全局函数确实可以解决问题,但是,让所有的类都知道并且调用一个全局函数/全局变量,跟调用它自己基类的某一个统一的接口,从使用者的角度来看,应该是后者更友好一些。

但是我仍然想知道,在大型的c++系统里,到底是怎么处理日志问题的,以及象上面那样做,跟它付出的代价相比,是不是值得?
windyJ 2001-12-30
  • 打赏
  • 举报
回复
也就是说基本上还是用第一种方案,只是把InfoLog类放到这个全局方法中?这样会不会不够OO?
alou 2001-12-30
  • 打赏
  • 举报
回复
对外部只提供一个全局的LogInfo()方法,将记录日志的功能委托给这个方法。
这个方法的内部使用InfoLog类,而InforLog类是不公开给需要记录日志的类的。
如果需要配置这个InfoLog类,那是配置程序的事情,与调用LogInfo()方法的类没有关系。

也有人会说用Singleton,但是我现在觉得Singleton并不是一种很漂亮的模式。
alou 2001-12-30
  • 打赏
  • 举报
回复
定位,自然是通过名字,而且需要有一个起点,通过他去询问,或者它就是你要找的人。
严格审批全局变量和函数,去掉“伪”全局函数(怎么检查我也说不好)。
假如使用你的第一种方法,用中文来描述:
所有的类都具有LogInfo()的能力(注:是具有能力,不是会使用能力),类在适当的时候使用这个能力去记录日志信息。在这个能力里面,日志信息首先被格式化成一个日志字符串,然后分配一个日志ID,最后写到日志文件里面去。
这还算简化的描述,显然,你的类的能力太强了。当然,类可以将这个能力保留,但是看看我们的周围,连学校都在将公寓和食堂外包。
另外,这种情况下,你计划怎么配置你的日志系统,比如说,怎么指定日志的存放文件?
fixopen 2001-12-30
  • 打赏
  • 举报
回复
别用继承!!建立一个LogManager类,只有方法,且全为静态的。直接LogManager::MembreFunction(args)使用就行了。如有个进一步的要求,LogManager用Template包一下就可以有静态成员变量了。
windyJ 2001-12-30
  • 打赏
  • 举报
回复
首先谢谢兄台,呵呵
你说的 “LogInfo()是一个服务”这个观点很好,我想也确实如此,这样看,重点就不同了。

我也是想把具体日志实现的地方独立出来,并且希望使用日志的类不会受影响,实际上用我第一种方法是可以做到这一点的,多做了一点的是把这个服务包括在类体系自己的接口中,然后在这个接口里调用一个全局函数(只在基类实现一次),也就是说,调用日志的类自己都有一个 公共的 通用的 接口,只要这个接口不变,日志类的实现变化一样不会影响到它们。

副作用是:类体系从一个基类继承,这也不算过分,因为java,delphi都是这样的,而且这个基类并不只是为了这个,它还可以做别的很多事情。

对,其实我就是不明白应该怎样去定位这个服务,怎样对一个系统才是合适的,以及如果出现满天的全局变量/全局函数会觉得心有惴惴焉。。。

还有别的办法吗? :)
sealcecily 2001-12-30
  • 打赏
  • 举报
回复
我也推!
gigix 2001-12-30
  • 打赏
  • 举报
回复
帮windy姐姐推一下。
alou 2001-12-30
  • 打赏
  • 举报
回复
何苦去O它?!
难道那些丑陋的象烂婆娘的裹脚布那样的参数表你喜欢吗?
不是第一种方法。类调用全局的LogInfo()方法,但是不是调用自己的类的LogInfo()成员方法。
我认为,你提出的第一种方法是滥用继承。假如一定要这样做,那么应该有一个类叫做:
ClassTendToLog(也就是你的整个类体系的基类),其它类从这里继承。这样很快你就会陷入多重继承的漩涡。而且,对这个功能的配置是一件很麻烦的事情 - 你计划在哪一个类的构造函数里面告诉LogInfo()需要把信息记录到哪一个文件里面去呢?
按照我的观点,LogInfo()是一个服务,服务的实现(比如说使用哪一个文件甚至是不是使用数据库),这些都和需要使用LogInfo()的类没有关系。这个服务的端点怎么命名或者寻找可以是灵活的(比如说,使用全局的LogInfo()方法或者提供一个全局的变量Logger甚至使用更高级的方法--J2EE里面使用目录来寻址)这都没有关系。
使用Log服务的类只需要知道两件事情:
1。找到Log服务。
2。正确调用LogInfo()方法。
简单了吧。

那么配置Log在哪里做呢?
Log服务有它的管理面,这个面包括了Log服务的参数的设置,实现上可能就是一个构造函数(长参数表可能在这里出现,但是你的大部分代码不会看见他),启动程序或者管理程序会正确调用这个面里面的方法,配置好这个Log服务,准备好接纳需要日志的类的请求。

一旦日志服务的实现发生变化,使用日志服务的类不需要进行任何改动,只要前面说道的两点变化,变动只是局限在启动程序或者管理程序里面。用类继承显然是达不到这种效果的。


当你已经察觉不到OO却又发现到处都是OO的时候,你掌握了OO。
windyJ 2001-12-30
  • 打赏
  • 举报
回复
up 各位请指点迷津



up

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧