我应该抛出什么类型的异常? 经过了异常处理(和,)的一些链接,我知道C++程序可以抛出任何异常作为例外( int > char *,字符串,异常< /Class >类。我知道std::exception是程序抛出的标准异常的基类。但是,我正在尝试设计一个try…catch块: try { MyFunc(); } catch (certain exceptions) { // deal with the exception accordingly } catch (the rest of the exceptions) { // deal with these accordingly }
而我应该抛出什么类型的异常? 经过了异常处理(和,)的一些链接,我知道C++程序可以抛出任何异常作为例外( int > char *,字符串,异常< /Class >类。我知道std::exception是程序抛出的标准异常的基类。但是,我正在尝试设计一个try…catch块: try { MyFunc(); } catch (certain exceptions) { // deal with the exception accordingly } catch (the rest of the exceptions) { // deal with these accordingly },c++,exception-handling,C++,Exception Handling,而MyFunc()包含以下内容: void MyFunc() { ... if (certain condition is true) throw exception; ... } 问题在于,在MyFunc函数的这一部分,我不确定应该抛出什么类型的异常。为了通过实现我自己的exceptions类保持代码整洁,我不知道实现此类exceptions类的好方法是什么 您可以从中派生自己的类,这样就有了统一处理异常的方法 如果这看起来有点过分,您可以抛出一个或另一个用于应用程序
MyFunc()
包含以下内容:
void MyFunc()
{
...
if (certain condition is true) throw exception;
...
}
问题在于,在
MyFunc
函数的这一部分,我不确定应该抛出什么类型的异常。为了通过实现我自己的exceptions类保持代码整洁,我不知道实现此类exceptions类的好方法是什么 您可以从中派生自己的类,这样就有了统一处理异常的方法
如果这看起来有点过分,您可以抛出一个或另一个用于应用程序的标准异常类型
您还可以将它们用作您自己更具体的异常的基类:这节省了一点工作,因为它们负责为您实现what
方法
请注意,深层异常层次结构可能无法使用,因为您基本上是在预先猜测如何对错误进行分类,而您的客户可能不同意。如果您可以使用boost,那么您应该这样做。请参阅,了解如何使用boost异常。您也可以按照其他答案所述设计自己的异常类层次结构,但您需要注意“what”方法中的“nothrow”需求等细微方面。下面解释了如何在boost::exception行上实现这一点的基本设计:-
#include <string>
#include <memory>
#include <stdexcept>
/************************************************************************/
/* The exception hierarchy is devised into 2 basic layers.
System exceptions and Logic exceptions. But Logic exceptions are
convertible to the ultimate base 'System' in the system layer.
*************************************************************************/
// the system exception layer
namespace ExH
{
namespace System {
// This is the only way to make predefined exceptions like
// std::bad_alloc, etc to appear in the right place of the hierarchy.
typedef std::exception Exception;
// we extend the base exception class for polymorphic throw
class BaseException : public Exception {
public:
BaseException() throw() {}
explicit BaseException(char const* /*desc*/) throw()
: Exception()
{}
BaseException(BaseException const& that)
: Exception(that)
{}
virtual void raise() const { throw *this; } // used to throw polymorphically
virtual ~BaseException() throw () {}
};
// module level classes compose and catch the descriptive
// versions of layer-exceptions
class DescriptiveException : public BaseException {
public:
explicit DescriptiveException (char const* description) throw()
: description_(description)
{ }
explicit DescriptiveException (std::string const& description) throw()
: description_(description.c_str())
{ }
virtual ~DescriptiveException () throw () {}
DescriptiveException (DescriptiveException const& src) throw()
: BaseException(src)
{
this->description_ = src.description_;
}
DescriptiveException& operator= (DescriptiveException const& src) throw()
{
if (this != &src)
{
this->description_ = src.description_;
}
return *this;
}
/*virtual*/ char const* what () const throw() { return description_; }
/*virtual*/ void raise() const // used to throw polymorphically
{ throw *this; }
protected:
DescriptiveException () throw ();
private:
char const* description_;
};
}
}
// the logic exception layer
namespace ExH
{
namespace Logic
{
// Logic::Exception inherits from System::Exception for the
// following reason. Semantically for some part of the
// system particular instance of Logic::Exception may seem as
// opaque System::Exception and the only way to handle it would
// be to propagate it further. In other words Logic::Exception
// can be seamlessly "converted" to System::Exception if there is
// no part of the system interested in handling it.
//
class BaseException : public System::BaseException
{
public:
BaseException() throw() {}
explicit BaseException(char const* desc) throw()
: System::BaseException(desc)
{}
BaseException(BaseException const& that)
: System::BaseException(that)
{}
virtual void raise() const { throw *this; } // used to throw polymorphically
virtual ~BaseException() throw () {}
};
// module level classes compose and catch the descriptive
// versions of layer-exceptions
class DescriptiveException : public BaseException {
public:
explicit
DescriptiveException (char const* description) throw()
: description_(new std::string(description))
{ }
explicit
DescriptiveException (std::string const& description) throw()
: description_(new std::string(description))
{ }
DescriptiveException(DescriptiveException const& src) throw()
: BaseException(src)
{
// copy the string
std::string* str = new std::string(src.description_.get()->c_str());
description_.reset(str);
}
virtual ~DescriptiveException () throw () {}
/*virtual*/ char const* what () const throw() { return description_->c_str(); }
/*virtual*/ void raise() const { throw *this; }
private:
DescriptiveException& operator= (DescriptiveException const& src) throw(); // copy disabled
std::auto_ptr<std::string> description_; // do not use std::string, as it can throw
};
}
}
/************************************************************************/
/* Users of the exception hierarchy compose specific exceptions as and
when needed. But they can always be caught at the System::Exception base
class level. Some of the standard conversion examples are demonstrated :-
class MyClass {
public:
class Exception_ {};
typedef
Compound <Exception_, Logic::DescriptiveException>
Exception;
class InvalidArgument_ {};
typedef
Compound <InvalidArgument_, Exception>
InvalidArgument;
class NotInitialized_ {};
typedef
Compound <NotInitialized_, Exception>
NotInitialized;
public:
void myFunction1() const throw(NotInitialized);
void myFunctionN() const throw(NotInitialized);
};
void MyClass::myFunction1() const {
throw NotInitialized("Not Inited!");
}
void MyClass::myFunctionN() const {
try {
// call myFunction1()
}
catch(NotInitialized const& e){
// use e
}
}
This has to be per-class basis. The exposed module will have an exception
specification which will catch all the sub-class exceptions. The calling
module will in turn rely on this exception-specification. This will allow
us to have generalized exception-catching at the application-level and
more specialized exception-catching at the specific module level. */
/************************************************************************/
// a simple template to compose the exceptions as per conversion requirements
namespace ExH
{
template <typename Type, typename Base>
class Compound : public Base
{
public:
explicit Compound (char const* description) throw ()
: Base(description)
{}
explicit Compound (std::string const& description) throw ()
: Base(description)
{}
Compound (Compound const& src) throw ()
: Base(src)
{}
virtual ~Compound () throw () {}
protected:
Compound () throw () {}
private:
Compound& operator= (Compound const& src) throw (); // disable copy
};
}
#包括
#包括
#包括
/************************************************************************/
/*异常层次结构设计为两个基本层。
系统异常和逻辑异常。但逻辑上的例外是
可转换为系统层中的最终基本“系统”。
*************************************************************************/
//系统异常层
命名空间ExH
{
名称空间系统{
//这是生成预定义异常的唯一方法,如
//std::bad_alloc等显示在层次结构的正确位置。
typedef std::异常异常;
//我们扩展了多态抛出的基本异常类
类BaseException:公共异常{
公众:
BaseException()throw(){}
显式BaseException(char const*/*desc*/)throw()
:Exception()
{}
BaseException(BaseException const&that)
:例外情况
{}
virtual void raise()常量{throw*this;}//用于以多态方式抛出
虚拟~BaseException()抛出(){}
};
//模块级类组成并捕获描述类
//层异常的版本
类DescriptiveException:公共BaseException{
公众:
显式DescriptiveException(char const*description)throw()
:说明(说明)
{ }
显式DescriptiveException(std::string const&description)throw()
:description_(description.c_str())
{ }
virtual~DescriptiveException()抛出(){}
DescriptiveException(DescriptiveException const&src)throw()
:BaseException(src)
{
此->说明=src.description;
}
DescriptiveException&operator=(DescriptiveException const&src)throw()
{
如果(此!=&src)
{
此->说明=src.description;
}
归还*这个;
}
/*virtual*/char const*what()const throw(){返回说明}
/*virtual*/void raise()const//用于以多态方式抛出
{扔*这个;}
受保护的:
DescriptiveException()抛出();
私人:
字符常量*描述;
};
}
}
//逻辑异常层
命名空间ExH
{
名称空间逻辑
{
//Logic::Exception继承自的System::Exception
//下面的原因。语义上为
//Logic::Exception的系统特定实例可能如下所示
//不透明系统::异常,处理它的唯一方法是
//它将进一步传播。换句话说,Logic::Exception
//如果存在异常,可以无缝地“转换”为System::Exception
//系统中没有任何部分对处理它感兴趣。
//
类BaseException:公共系统::BaseException
{
公众:
BaseException()throw(){}
显式BaseException(char const*desc)throw()
:System::BaseException(描述)
{}
BaseException(BaseException const&that)
:System::BaseException(即)
{}
virtual void raise()常量{throw*this;}//用于以多态方式抛出
虚拟~BaseException()抛出(){}
};
//模块级类组成并捕获描述类
//层异常的版本
类DescriptiveException:公共BaseException{
公众:
明确的
DescriptiveException(char const*description)throw()
:description_(新标准::字符串(说明))
{ }
明确的
DescriptiveException(std::string const&description)throw()
:description_(新标准::字符串(说明))
{ }
DescriptiveException(DescriptiveException const&src)throw()
:BaseException(src)
{
//复制字符串
std::string*str=新的std::string(src.description_u.get()->c_str());
说明.复位(str);
}
virtual~DescriptiveException()抛出(){}
/*virtual*/char const*what()const throw(){return description->c_str();}
/*虚拟*/void r
//---------------------------------------------------------------------------
// 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
//---------------------------------------------------------------------------
// 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
#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;
}
class my_exception : public std::runtime_error
{
public:
my_exception(const std::string& msg)
: std::runtime_error(msg)
{ }
};