Fir*_*cer 42 c++ exception-handling exception
什么是一组异常类的好设计?
我看到各种各样的东西,关于什么异常类应该和不应该做什么,但不是一个简单的设计,易于使用和扩展,做那些事情.
让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];
};
Run Code Online (Sandbox Code Playgroud)
由于所有字符串都是通过复制到内部固定大小的缓冲区来处理(如果需要截断,但始终为空终止),则处理点1.
虽然这不涉及第3点,但我认为这一点很可能在现实世界中有限使用,并且很可能通过在需要时抛出新的异常来解决.
Adr*_*thy 24
使用浅层次的异常类.使层次结构过于深入会增加复杂性而不是价值.
从std :: exception(或其他标准异常之一,如std :: runtime_error)派生异常类.这允许顶级的通用异常处理程序处理您不能处理的任何异常.例如,可能存在记录错误的异常处理程序.
如果这是针对特定库或模块的,则可能需要特定于模块的基础(仍然来自其中一个标准异常类).呼叫者可能决定以这种方式从您的模块中捕获任何内容.
我不会做太多的异常类.您可以在类中包含有关异常的大量详细信息,因此您不一定需要为每种错误创建唯一的异常类.另一方面,您确实需要您希望处理的错误的唯一类.如果您正在创建解析器,则可能只有一个syntax_error异常,其成员描述问题的详细信息,而不是针对不同类型的语法错误的一堆特殊问题.
异常中的字符串用于调试.您不应该在用户界面中使用它们.您希望将UI和逻辑尽可能分开,以实现翻译成其他语言的功能.
您的异常类可以包含额外字段,其中包含有关问题的详细信 例如,syntax_error异常可能具有源文件名,行号等.尽可能坚持这些字段的基本类型,以减少构造或复制异常以触发另一个异常的机会.例如,如果必须在异常中存储文件名,则可能需要一个固定长度的普通字符数组,而不是std :: string.std :: exception的典型实现使用malloc动态分配原因字符串.如果malloc失败,他们将牺牲原因字符串而不是抛出嵌套异常或崩溃.
C++中的例外应该是"特殊"条件.所以解析示例可能不是很好.解析文件时遇到的语法错误可能不够特殊,无法保证由异常处理.如果程序可能无法继续,除非条件被明确处理,我会说一些例外情况.因此,大多数内存分配失败都是例外,但用户的错误输入可能不是.
2:不,您不应该将用户界面(=本地化消息)与程序逻辑混合在一起.当应用程序意识到它无法处理问题时,应在外层完成与用户的通信.异常中的大多数信息都是过多的实现细节,无论如何都无法向用户显示.
3:对此
5 使用boost.exception
:不要这样做.请参阅2.记录的决定应始终位于错误处理站点.
不要只使用一种类型的例外.使用足够的类型,以便应用程序可以为所需的每种类型的错误恢复使用单独的catch处理程序
小智 2
一个好的设计不是创建一组异常类 - 只需基于 std::exception 为每个库创建一个异常类。
添加信息相当简单:
try {
...
}
catch( const MyEx & ex ) {
throw MyEx( ex.what() + " more local info here" );
}
Run Code Online (Sandbox Code Playgroud)
异常处理程序拥有它们需要的信息,因为它们是异常处理程序——只有 try 块中的函数才能引发异常,因此处理程序只需要考虑那些错误。而不是你真的不应该使用异常来进行一般错误处理。
基本上,异常应该尽可能简单 - 有点像日志文件,它们应该没有直接联系。
我想以前有人问过这个问题,但现在找不到。
归档时间: |
|
查看次数: |
32648 次 |
最近记录: |