为什么std :: logic_error实际上不会从std :: exception继承? [英] Why does std::logic_error not virtually inherit from std::exception?

查看:358
本文介绍了为什么std :: logic_error实际上不会从std :: exception继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现自定义异常层次结构,并允许代码捕获适当的std :: *.

class my_exception : public virtual std::exception {
};
class my_bad_widget_state : public virtual my_exception, public virtual std::logic_error {
   public: my_bad_widget_state() : std::logic_error("widget oops") {}
};

很显然,my_bad_widget_state是一个my_exception,也是std :: logic_error,但是编译器拒绝此代码,因为在继承异常时std :: exception不会说虚,因此存在歧义.编译器是正确的,但我认为标准库可能是错误的,还是?

修改: 显然,my_bad_widget_state是一个my_exception,因此是一个逻辑错误,也是一个std :: exception,并且当引发my_bad_widget_state时,不会捕获std :: exception.

修改: 我有兴趣知道标准库是否是出于目前我无法理解的特定原因(如果是这样,请问该原因是什么)还是某种疏忽而设计的.我的研究表明,很多人似乎都认为这是一个问题,但是我没有发现继承不应该是虚拟的任何原因.

Q1:为什么标准库中的继承不是虚拟的?

Q2:如何正确实施? [已回答]

解决方案

[W]为什么继承[w.r.t.例外]在标准库中不是虚拟的?

简单来说,标准异常层次结构中的多重继承是不受支持的.它实际上不是派生的,实际上是它的含义.

相比之下,这在标准库中的哪个位置受支持? I/O流是我想到的第一个示例.特别是在层次结构一直到basic_iostream的范围内一直使用basic_ios.在这种情况下,原本是为了支持多重继承而实际上衍生出碱基,并且避免了钻石问题".

那为什么为什么要使用std::exception?

std::exception 具有多个从中派生的异常,特别是,请注意 std::logic_error 请参见此处

如何处理增强异常?

Boost使用虚拟继承,他们这样做是为了完全支持标准库不支持的多重继承.它还支持标准库中未提供的一些其他功能.

也就是说,boost仍然使用std::exception作为基类.

最终,这将成为您希望在层次结构中支持的继承结构的设计决策.

I'm trying to implement a custom exception hierarchy and allow appropriate std::* to be caught by code.

class my_exception : public virtual std::exception {
};
class my_bad_widget_state : public virtual my_exception, public virtual std::logic_error {
   public: my_bad_widget_state() : std::logic_error("widget oops") {}
};

Obviously my_bad_widget_state is a my_exception and is also a std::logic_error, but the compiler rejects this code because std::exception doesn't say virtual when inheriting exception so there's an ambiguity. The compiler is right, but I think the standard library might be wrong, or?

edit: Obviously my_bad_widget_state is a my_exception so a logic_error and also a std::exception, and when my_bad_widget_state is thrown std::exception is not being caught.

edit: I am interested in knowing whether the standard library is designed this way for a particular reason that I failed to understand so far (if so, what is that reason please) or is it some kind of an oversight. My research indicates that many people seem to think this is a problem, but I didn't find any reason the inheritance shouldn't be virtual.

Q1: why is the inheritance in the standard library not virtual?

Q2: how can this be implemented correctly? [answered]

解决方案

[W]hy is the inheritance [w.r.t. exceptions] in the standard library not virtual?

Simply, multiple inheritance, in the standard exception hierarchy, wasn't intended to be supported. It is not virtually derived, and this is, in effect, what it means.

By contrast, where in the standard library is this supported? I/O streams is the first example that comes to mind. In particular the use of basic_ios all the way down the hierarchy to basic_iostream. In this case, it was intended that the base was virtually derived to support the multiple inheritance and that the "diamond problem" was avoided.

So why is this, how should std::exception be used?

std::exception has multiple exceptions that are derived from it, in particular, note the std::logic_error and std::runtime_error. The standard library has already given us a board pattern for classification and organisation of our exceptions, namely;

class logic_error;

Defines a type of object to be thrown as exception. It reports errors that are a consequence of faulty logic within the program such as violating logical preconditions or class invariants and may be preventable.

And

class runtime_error;

Defines a type of object to be thrown as exception. It reports errors that are due to events beyond the scope of the program and can not be easily predicted.

Of course these are not the only two, but they capture and are a base of a significant number of other standard library exceptions.

Where to root the exception hierarchy?

  • If you wish to use the standard library exception hierarchy, it is better to choose a point at which to extend the hierarchy and work from that point on. Hence, if there is a desire to have a custom root exception, then have std::exception as a base class and derive further custom exceptions from that custom base onwards.

  • If the custom exceptions are divisible between runtime and logic errors, then derive the custom exception hierarchy from that level onwards.

Using a custom exception hierarchy rooted somewhere in the standard library exceptions is generally a good idea. At what point that root(s) should be is dependent on the actual intended use of the code. See here for a broader Q&A on this.

What about boost exceptions?

Boost uses virtual inheritance, they do this to exactly support the multiple inheritance that the standard library does not support. It also supports some additional features not found in the standard library.

That said, boost still uses the std::exception as a base class.

Ultimately this becomes a design decision based on the inheritance structures you wish to support in the hierarchy.

这篇关于为什么std :: logic_error实际上不会从std :: exception继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆