C+中的自定义异常+; 我一直在尝试为我正在处理的C++库制作一些自定义异常类。这些自定义异常捕获调试所需的额外信息,如文件、行号等,如果测试时由于某种原因未在正确的位置捕获异常。然而,大多数人似乎都建议从STL中的std::exception类继承,我同意这一点,但我想知道,如果使用多重继承从每个(例如std::runtime_error)和自定义异常类继承,可能会更好,如下面的代码所示

C+中的自定义异常+; 我一直在尝试为我正在处理的C++库制作一些自定义异常类。这些自定义异常捕获调试所需的额外信息,如文件、行号等,如果测试时由于某种原因未在正确的位置捕获异常。然而,大多数人似乎都建议从STL中的std::exception类继承,我同意这一点,但我想知道,如果使用多重继承从每个(例如std::runtime_error)和自定义异常类继承,可能会更好,如下面的代码所示,c++,stl,exception,multiple-inheritance,C++,Stl,Exception,Multiple Inheritance,另一件事,如何在异常类中复制构造函数和赋值运算符?他们应该被禁用吗 class Exception{ public: explicit Exception(const char *origin, const char *file, const int line, const char *reason="", const int errno=0) throw();

另一件事,如何在异常类中复制构造函数和赋值运算符?他们应该被禁用吗

class Exception{
    public:
        explicit Exception(const char *origin, const char *file, 
                           const int line, const char *reason="", 
                           const int errno=0) throw();

        virtual ~Exception() throw();

        virtual const char* PrintException(void) throw();

        virtual int GetErrno(void);

    protected:
        std::string m_origin;
        std::string m_file;
        int m_line;
        std::string m_reason;
        int m_errno;
}; 

class RuntimeError: public virtual std::runtime_error, public Exception{
    public:
              explicit RuntimeError(const char *origin, const char *file, 
                                    const int line, const char *reason="", 
                                    const int errno=0) throw();
        virtual ~RuntimeError() throw();
};
你应该试试

Boost异常的目的是 简化异常类的设计 层次结构和帮助编写 异常处理和错误报告 代码

它支持任意数据的传输 将数据发送到catch站点,即 由于没有投掷,其他方面很棘手 例外情况的要求(15.5.1) 类型。数据可以添加到任何 异常对象,或者直接在 抛出表达式(15.1),或在 稍后将时间作为异常对象 向上传播调用堆栈

向异常添加数据的能力 对象在传递给之后 投掷很重要,因为通常有些 处理一个问题所需的信息 异常在中不可用 检测到故障的上下文

Boost异常还支持 N2179异常的样式复制 对象,以非侵入方式实现 并自动由 boost::抛出异常函数

我想知道使用多重继承来继承每个派生的std::exception类是否更好

请注意,这是一个问题,因为标准库中的异常非虚拟地彼此派生。如果引入多重继承,则在没有虚拟继承的情况下会得到可怕的菱形异常层次结构,并且将无法通过
std::exception&
捕获派生异常,因为派生异常类包含两个子对象
std::exception
,从而使
std::exception
成为“不明确的基类”

具体例子:

class my_exception : virtual public std::exception {
  // ...
};

class my_runtime_error : virtual public my_exception
                       , virtual public std::runtime_error {
  // ...
};
现在,
my_runtime_error
std::exception
两次间接派生,一次通过
std::run_time_error
和一次通过
my_exception
。由于前者实际上不是从
std::exception
派生的,因此

try {
  throw my_runtime_error(/*...*/);
} catch( const std::exception& x) {
  // ...
}
不行

编辑:

我想我在Stroustrup的一本书中看到了涉及MI的异常类层次结构的第一个示例,所以我得出结论,一般来说,这是一个好主意。事实上,STD LIB的例外并不是从我认为是失败的事实中派生出来的。p> 当我上次设计异常层次结构时,我非常广泛地使用了MI,但没有从std库的异常类派生。在这个层次结构中,有一些抽象异常类,您定义这些类是为了让用户能够捕获它们,还有相应的实现类,它们是从这些抽象类和实现基类派生的,您实际上会抛出它们。为了简化这一过程,我定义了一些模板,这些模板将完成所有艰苦的工作:

// something.h
class some_class {
private:
  DEFINE_TAG(my_error1); // these basically define empty structs that are needed to 
  DEFINE_TAG(my_error2); // distinguish otherwise identical instances of the exception 
  DEFINE_TAG(my_error3); // templates from each other (see below)
public:
  typedef exc_interface<my_error1>  exc_my_error1;
  typedef exc_interface<my_error2>  exc_my_error2;
  typedef exc_interface<my_error3,my_error2> // derives from the latter
                                    exc_my_error3;

  some_class(int i);
  // ...
};

//something.cpp
namespace {
  typedef exc_impl<exc_my_error1> exc_impl_my_error1;
  typedef exc_impl<exc_my_error2> exc_impl_my_error2;
  typedef exc_impl<exc_my_error3> exc_impl_my_error3;
  typedef exc_impl<exc_my_error1,exc_my_error2> // implements both
                                  exc_impl_my_error12;
}
some_class::some_class(int i)
{
  if(i < 0) 
    throw exc_impl_my_error3( EXC_INFO  // passes '__FILE__', '__LINE__' etc.
                            , /* ... */ // more info on error
                            ); 
}
//something.h
上课{
私人:
DEFINE_TAG(my_error1);//这些基本上定义了需要的空结构
DEFINE_TAG(my_error2);//区分异常的其他相同实例
定义_标记(my_error3);//相互之间的模板(见下文)
公众:
类型定义exc_接口exc_我的错误1;
类型定义exc_接口exc_我的错误2;
typedef exc_接口//派生自后者
执行我的错误3;
某些_类(inti);
// ...
};
//某物
名称空间{
typedef exc_impl exc_impl_my_error 1;
typedef exc_impl exc_impl_my_error 2;
typedef exc_impl exc_impl_my_error 3;
typedef exc_impl//实现这两个功能
执行我的错误12;
}
some_类::some_类(inti)
{
if(i<0)
抛出exc_impl_my_error 3(exc_INFO//passes'\uu FILE_uuuuuuuuuuuu'、'\uuuuu LINE_uuuuuuuuuuu'等)。
,//*…*///有关错误的详细信息
); 
}

现在回过头来看,我认为我可以使
exc_impl
类模板从
std::exception
(或std lib exception层次结构中的任何其他类,作为可选模板参数传递),因为它从未从任何其他
exc_impl
实例派生。但那时候不需要这样,所以我从来没有想过

你会从中得到什么?为什么不使用单一继承?为什么需要自定义异常和RuntimeError异常?我想使用自定义异常类中的功能,并通过继承各种派生的std::Exception类来维护STL异常层次结构。这样一个catch:try{throw RunTimeException(…);}catch(std::runtime_error&e){…}catch(std::exception&e){…}也可以捕获我的自定义类。但这可能是浪费时间。我也可以尝试{throw RunTimeException(…);}catch(std::exception&e){…},但这样会使识别异常变得更加困难。我不知道自定义异常类时的典型实践是什么?我会说只是从std::runtime_错误(或std::exception)继承。如果你想要一个特殊的治疗,你可以有多个捕手。(特别是在C++中)。更易于使用的代码,如
boost::exception
,经过广泛的同行评审和战斗测试。我以前从未使用过boost。我会调查的。谢谢你的帖子。谢谢你的帖子。使用多重继承生成异常类是一种好的做法吗?还是从std::exception类继承更好?但他没有这个问题。你已经走了