通过一些关于异常处理的链接(1,我知道C++程序可以抛出几乎任何异常(int
、char*
、string
、exception
类)。我知道std::exception
是程序抛出的标准异常的基类。但是,我正在尝试设计一个try
...catch
块,如下所示:
try
{
MyFunc();
}
catch (certain exceptions)
{
// deal with the exception accordingly
}
catch (the rest of the exceptions)
{
// deal with these accordingly
}
而MyFunc()
包含以下内容:
void MyFunc()
{
...
if (certain condition is true) throw exception;
...
}
问题在于,在MyFunc
函数的这一部分,我不确定应该抛出哪种类型的异常。为了通过实现我自己的exceptions类来保持代码的整洁,我不知道实现这样的exceptions类的好方法是什么。
发布于 2009-07-21 06:51:38
您可以从std::exception
派生自己的类,这样就有了某种方法来统一处理异常。
如果这看起来有点过分,您可以抛出std::logic_error
或其他供应用程序使用的标准异常类型。
您还可以将它们用作您自己的更具体异常的基类:这节省了一些工作,因为它们负责为您实现what
方法。
请注意,深度异常层次结构可能是不可用的,因为您基本上是提前猜测如何对错误进行分类,而您的客户可能不同意。
发布于 2009-07-21 09:23:18
下面是一个代码片段,它展示了如何扩展和使用std::exception类:(顺便说一句,这段代码有一个bug,我将在后面解释)。
#include <iostream>
#include <string>
#include <exception>
class my_exception : public std::exception
{
public:
explicit my_exception(const std::string& msg)
: msg_(msg)
{}
virtual ~my_exception() throw() {}
virtual const char* what() const throw()
{
return msg_.c_str();
}
private:
std::string msg_;
};
void my_func() throw (my_exception&)
{
throw my_exception("aaarrrgggg...");
}
int
main()
{
try
{
my_func();
}
catch (my_exception& ex)
{
std::cout << ex.what() << '\n';
}
return 0;
}
请注意,构造函数是显式的,而析构函数和what()被声明(使用throw())以指示它们本身不会抛出异常。这就是bug所在的地方。可以保证对msg_.c_str()的调用不会抛出自己的异常吗?那我们用来初始化msg_的字符串构造函数呢?它还可以引发异常。我们如何设计一个不受成员对象引发的异常影响的异常类呢?答案是-从std::runtime_error或类似的std::exception子类继承。因此,实现my_exception的正确方法应该是:
class my_exception : public std::runtime_error
{
public:
my_exception(const std::string& msg)
: std::runtime_error(msg)
{ }
};
我们不需要重写what(),因为它已经在std::runtime_error中实现了。消息缓冲区的正确处理是由std::runtime_error完成的,因此我们可以确保my_exception本身不会在运行时抛出一些未知的错误。
发布于 2009-07-21 07:33:47
我想发布一些真实的代码来改变一下可能会很有趣。这是我自己的工具库使用的异常类:
//---------------------------------------------------------------------------
// a_except.h
//
// alib exception handling stuff
//
// Copyright (C) 2008 Neil Butterworth
//---------------------------------------------------------------------------
#ifndef INC_A_EXCEPT_H
#define INC_A_EXCEPT_H
#include "a_base.h"
#include <exception>
#include <sstream>
namespace ALib {
//------------------------------------------------------------------------
// The only exception thrown directly by alib
//------------------------------------------------------------------------
class Exception : public std::exception {
public:
Exception( const std::string & msg = "" );
Exception( const std::string & msg, int line,
const std::string & file );
~Exception() throw();
const char *what() const throw();
const std::string & Msg() const;
int Line() const;
const std::string & File() const;
private:
std::string mMsg, mFile;
int mLine;
};
//------------------------------------------------------------------------
// Macro to throw an alib exception with message formatting.
// Remember macro is not in ALib namespace!
//------------------------------------------------------------------------
#define ATHROW( msg ) \
{ \
std::ostringstream os; \
os << msg; \
throw ALib::Exception( os.str(), __LINE__, __FILE__ ); \
} \
} // namespace
#endif
这是.cpp文件:
//---------------------------------------------------------------------------
// a_except.h
//
// alib exception handling stuff
//
// Copyright (C) 2008 Neil Butterworth
//---------------------------------------------------------------------------
#include "a_except.h"
using std::string;
namespace ALib {
//---------------------------------------------------------------------------
// exception with optional message, filename & line number
//------------------------------------------------------------------------
Exception :: Exception( const string & msg )
: mMsg( msg ), mFile( "" ), mLine(0) {
}
Exception :: Exception( const string & msg, int line, const string & file )
: mMsg( msg ), mFile( file ), mLine( line ) {
}
//---------------------------------------------------------------------------
// Do nothing
//---------------------------------------------------------------------------
Exception :: ~Exception() throw() {
}
//------------------------------------------------------------------------
// message as C string via standard what() function
//------------------------------------------------------------------------
const char * Exception :: what() const throw() {
return mMsg.c_str();
}
//------------------------------------------------------------------------
// as above, but as C++ string
//------------------------------------------------------------------------
const string & Exception :: Msg() const {
return mMsg;
}
//---------------------------------------------------------------------------
// File name & line number
//---------------------------------------------------------------------------
int Exception :: Line() const {
return mLine;
}
const string & Exception :: File() const {
return mFile;
}
} // namespace
// end
https://stackoverflow.com/questions/1157591
复制相似问题