以下代码生成“Looser throw specifier error”。你能帮我解决这个错误吗?
class base
{
virtual void abc() throw (exp1);
}
void base::abc() throw (exp1)
{
......
}
class sub : public base
{
void abc() throw(exp1, exp2);
}
void sub::abc() throw (exp1, exp2)
{
.....
}
答案 0 :(得分:13)
问题出现了,因为子类必须可以在任何可以使用基类的地方使用,因此不能抛出除基类中指定的异常类型之外的任何异常类型。
有三种解决方案:
我建议删除它们;他们被广泛认为是一个坏主意,部分是因为这样的问题。正如Matthieu所指出的那样,标准委员会同意,并且在下一版本的标准中,异常说明符将被弃用。
答案 1 :(得分:6)
当您在派生类中使用throw说明符覆盖虚方法时,派生类中的方法不会抛出比超类中的方法更多的异常。如果您被允许这样做,您可以通过覆盖子类中的方法来破坏超类的公共API创建的合同。
在你的例子中,你说base :: abc只能抛出exp1。但是,如果你有一个类型为base的指针,它实际上是指向sub的一个实例,那么突然abc除了exp1之外还可以抛出exp2。
要解决此问题,您需要从子类中的throw说明符中删除exp2,或者将exp2添加到超类的throw说明符中。
答案 2 :(得分:3)
假设我尝试
base *b = new sub;
b->abc();
基于base::abc
中的throw说明符,我希望它只会抛出exp1
;但sub::abc
表示它也可能会抛出exp2
。
如果sub::abc
可以真正抛出exp2
,则将exp2
添加到base::abc
可以投掷的列表中。如果没有,请将其从sub::abc
列表中删除。
更好:不要使用throw说明符。有关详细信息,请参阅Can anyone explain C++ exception specifications to me?和http://www.gotw.ca/publications/mill22.htm。