首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我应该抛出什么类型的异常?

我应该抛出什么类型的异常?
EN

Stack Overflow用户
提问于 2009-07-21 06:39:44
回答 5查看 11.1K关注 0票数 19

通过一些关于异常处理的链接(1,我知道C++程序可以抛出几乎任何异常(intchar*stringexception类)。我知道std::exception是程序抛出的标准异常的基类。但是,我正在尝试设计一个try...catch块,如下所示:

代码语言:javascript
复制
try
{
    MyFunc();
}
catch (certain exceptions)
{
    // deal with the exception accordingly
}
catch (the rest of the exceptions)
{
    // deal with these accordingly
}

MyFunc()包含以下内容:

代码语言:javascript
复制
void MyFunc()
{
    ...
    if (certain condition is true) throw exception;
    ...
}

问题在于,在MyFunc函数的这一部分,我不确定应该抛出哪种类型的异常。为了通过实现我自己的exceptions类来保持代码的整洁,我不知道实现这样的exceptions类的好方法是什么。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-07-21 06:51:38

您可以从std::exception派生自己的类,这样就有了某种方法来统一处理异常。

如果这看起来有点过分,您可以抛出std::logic_error或其他供应用程序使用的标准异常类型。

您还可以将它们用作您自己的更具体异常的基类:这节省了一些工作,因为它们负责为您实现what方法。

请注意,深度异常层次结构可能是不可用的,因为您基本上是提前猜测如何对错误进行分类,而您的客户可能不同意。

票数 20
EN

Stack Overflow用户

发布于 2009-07-21 09:23:18

下面是一个代码片段,它展示了如何扩展和使用std::exception类:(顺便说一句,这段代码有一个bug,我将在后面解释)。

代码语言:javascript
复制
#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的正确方法应该是:

代码语言:javascript
复制
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本身不会在运行时抛出一些未知的错误。

票数 12
EN

Stack Overflow用户

发布于 2009-07-21 07:33:47

我想发布一些真实的代码来改变一下可能会很有趣。这是我自己的工具库使用的异常类:

代码语言:javascript
复制
//---------------------------------------------------------------------------
// 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文件:

代码语言:javascript
复制
//---------------------------------------------------------------------------
// 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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1157591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档