如何向类添加错误记录器
我想使用通用错误消息处理程序,这样我就可以为任何类轻松地 GetLastError
和 SetError
。我想出了这个方案。但我有几个问题。请注意,此实现仅用于测试。但我想让基本设计正确。
#include <iostream>
#include <stdarg.h>
class ErrorHandler
{
public:
virtual void SetError(const char* zFormat, ...)
{
va_list args;
va_start (args, zFormat);
vsnprintf (z_ErrorBuf, sz_MaxBufSize, zFormat, args);
va_end (args);
}
const char* GetError() const
{
return z_ErrorBuf;
}
virtual ~ErrorHandler(){}
explicit ErrorHandler(const size_t szMaxBufSize = 1024)
{
z_ErrorBuf = malloc(sizeof(char)*szMaxBufSize);
sz_MaxBufSize = szMaxBufSize;
}
void ResizeBuffer(const size_t szMaxBufSize)
{
z_ErrorBuf = realloc(z_ErrorBuf, szMaxBufSize);
sz_MaxBufSize = szMaxBufSize;
}
protected:
char* z_ErrorBuf;
size_t sz_MaxBufSize;
};
class MyClass;
//Worker can be just an interface if needed. So, can't use friend.
class Worker
{
public:
void Work(MyClass& oGod);
};
void Worker::Work(MyClass& oGod)
{
//Work
//OnError
oGod.GetErrorHandler().SetError("Save me %s", "not");
}
class RecordingErrors
{
public:
const char* GetLastError() const
{
return oErrorHandler.GetError();
}
//GetErrorHandler is public
ErrorHandler& GetErrorHandler()
{
return oErrorHandler;
}
private:
ErrorHandler oErrorHandler;
};
class MyClass : public RecordingErrors
{
public:
bool GetThingsDone(Worker& me)
{
me.Work(*this);
//on Error
return false;
}
};
int main()
{
MyClass oL;
Worker w;
if(!oL.GetThingsDone(w))
{
std::cout << oL.GetLastError() << std::endl;
}
}
- 我可以在子类中重写这个函数吗?
virtual void SetError(const char* zFormat, ...)
。 - 我可以取消
RecordingErrors
类吗?我觉得MyClass
必须继承ErrorHandler
,我认为这不好。我是对还是错?这是关于组合而不是继承的另一个问题吗?编辑:我的意思不是名字,而是想法? - 这种方法有什么可能失败的情况吗?
- 有没有更好的方法来实现错误日志记录?(日志记录在这里不是正确的词。它是什么)
I would like to use a generic error msg handler so I can GetLastError
and SetError
easily for any class. I came up with this scheme. But I have a couple of questions. Please note this implementation is just for testing. But I want to get the basic design right.
#include <iostream>
#include <stdarg.h>
class ErrorHandler
{
public:
virtual void SetError(const char* zFormat, ...)
{
va_list args;
va_start (args, zFormat);
vsnprintf (z_ErrorBuf, sz_MaxBufSize, zFormat, args);
va_end (args);
}
const char* GetError() const
{
return z_ErrorBuf;
}
virtual ~ErrorHandler(){}
explicit ErrorHandler(const size_t szMaxBufSize = 1024)
{
z_ErrorBuf = malloc(sizeof(char)*szMaxBufSize);
sz_MaxBufSize = szMaxBufSize;
}
void ResizeBuffer(const size_t szMaxBufSize)
{
z_ErrorBuf = realloc(z_ErrorBuf, szMaxBufSize);
sz_MaxBufSize = szMaxBufSize;
}
protected:
char* z_ErrorBuf;
size_t sz_MaxBufSize;
};
class MyClass;
//Worker can be just an interface if needed. So, can't use friend.
class Worker
{
public:
void Work(MyClass& oGod);
};
void Worker::Work(MyClass& oGod)
{
//Work
//OnError
oGod.GetErrorHandler().SetError("Save me %s", "not");
}
class RecordingErrors
{
public:
const char* GetLastError() const
{
return oErrorHandler.GetError();
}
//GetErrorHandler is public
ErrorHandler& GetErrorHandler()
{
return oErrorHandler;
}
private:
ErrorHandler oErrorHandler;
};
class MyClass : public RecordingErrors
{
public:
bool GetThingsDone(Worker& me)
{
me.Work(*this);
//on Error
return false;
}
};
int main()
{
MyClass oL;
Worker w;
if(!oL.GetThingsDone(w))
{
std::cout << oL.GetLastError() << std::endl;
}
}
- Can I override this function in a child class?
virtual void SetError(const char* zFormat, ...)
. - Can I do away with the
RecordingErrors
class? I feel that thenMyClass
would have to inherit fromErrorHandler
which I don't think is good. Am I right or wrong? Is this another question about composition over inheritence. EDIT: I don't mean the name, but the idea? - Any possible scenarios this approach would fail?
- is there a better way to implement error logging?(logging is not the right word here. What is it)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
错误处理程序和记录器是两个不同的实体。错误处理程序决定如何处理错误。应该立即发送到记录器,应该将其保存在数据库中,还是应该简单地保存在某个缓冲区中直到有人询问。
记录器决定如何记录给定的消息。它应该显示在控制台上还是应该保存在磁盘文件中,应该以什么格式显示。
请记住记录器的功能。
1)它应该是独立的类。它的行为不应该依赖于其他类。
2)记录器最好是单例的。您不需要许多漂浮的物体做同样的事情。但是单例类在多线程方面也有自己的麻烦。所以我知道这一点是有争议的。
3)它必须并且必须具有异步日志记录的能力。这意味着生产者和消费者的实现。 (日志记录是一种 I/O 操作,因此本质上是昂贵的。您不希望主处理占用此操作。但话又说回来,您可能不想使用线程来废弃这个操作。)
在错误记录器的实现中,我可以没有看到任何记录器。此外,您的错误处理程序正在保存一个错误。您可能需要错误向量。将 SetError 保留为固定参数。传递错误 ID、错误消息和错误缓冲区长度等参数。让调用者创建错误消息。
Error Handler and logger are two different entities. Error handler decides what to do with the errors. Should it be send to logger immediately, should it be saved in databases, or should it be simply saved in some buffer till someone asks.
Logger decides how to log the given message. Should it be shown on the console or should it be saved in the disk file, in what format it should be shown.
Keep in mind the features of the logger.
1) It should be independent class. It's behavior should not depend on the other classes.
2) Logger most preferable should be singleton. You don't need many objects floating around doing the same thing. But then singleton classes has their own headaches when come to multi-threading. So I know this point is debatable.
3) It must and must have capabilities of asynchronous logging. This means producer and consumer implementation. (Logging is an i/o operation and hence expensive in nature. You don't want your main processing hogging for this. But then again you may not want to use threads to scrap this one.)
In you implementation of error logger I can't see any logger. Also your error handler is saving a single error. You may need the vector of errors. Keep SetError with fixed arguments. Pass arguments like error id, error message and error buffer length. Let the caller create the error message.