【发布时间】:2009-08-26 15:27:45
【问题描述】:
一组异常类的好的设计是什么?
我看到各种关于异常类应该做什么和不应该做什么的事情,但不是一个易于使用和扩展的简单设计来做这些事情。
- 异常类不应抛出异常,因为这可能会直接导致进程终止而没有机会记录错误等。
- 需要能够获得用户友好的字符串,最好是本地化为他们的语言,以便在应用程序无法从错误中恢复时自行终止之前告诉他们一些事情。
- 需要能够在堆栈展开时添加信息,例如,如果 XML 解析器无法解析输入流,则能够添加源来自文件或通过网络等。
- 异常处理程序需要轻松访问处理异常所需的信息。
- 将格式化的异常信息写入日志文件(英文,所以这里没有翻译)。
让 1 和 4 一起工作是我遇到的最大问题,因为任何格式化和文件输出方法都可能失败。
编辑: 因此,在查看了几个类中的异常类以及 Neil 所链接的问题之后,完全忽略第 1 项(以及提升建议)似乎是一种常见的做法,这对我来说似乎是一个相当糟糕的主意。
无论如何,我想我也会发布我正在考虑使用的异常类。
class Exception : public std::exception
{
public:
// Enum for each exception type, which can also be used
// to determine the exception class, useful for logging
// or other localisation methods for generating a
// message of some sort.
enum ExceptionType
{
// Shouldn't ever be thrown
UNKNOWN_EXCEPTION = 0,
// The same as above, but it has a string that
// may provide some information
UNKNOWN_EXCEPTION_STR,
// For example, file not found
FILE_OPEN_ERROR,
// Lexical cast type error
TYPE_PARSE_ERROR,
// NOTE: in many cases functions only check and
// throw this in debug
INVALID_ARG,
// An error occured while trying to parse
// data from a file
FILE_PARSE_ERROR,
}
virtual ExceptionType getExceptionType()const throw()
{
return UNKNOWN_EXCEPTION;
}
virtual const char* what()throw(){return "UNKNOWN_EXCEPTION";}
};
class FileOpenError : public Exception
{
public:
enum Reason
{
FILE_NOT_FOUND,
LOCKED,
DOES_NOT_EXIST,
ACCESS_DENIED
};
FileOpenError(Reason reason, const char *file, const char *dir)throw();
Reason getReason()const throw();
const char* getFile()const throw();
const char* getDir ()const throw();
private:
Reason reason;
static const unsigned FILE_LEN = 256;
static const unsigned DIR_LEN = 256;
char file[FILE_LEN], dir[DIR_LEN];
};
解决了第 1 点,因为所有字符串都是通过复制到内部固定大小的缓冲区来处理的(如果需要,会截断,但总是以 null 结尾)。
虽然这没有解决第 3 点,但我认为该点很可能在现实世界中使用有限,并且很可能通过在需要时抛出新异常来解决。
【问题讨论】:
标签: c++ exception exception-handling