C ++中的松散抛出说明符错误

时间:2011-03-11 07:03:17

标签: c++ exception

以下代码生成“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)
{
    .....
}

3 个答案:

答案 0 :(得分:13)

问题出现了,因为子类必须可以在任何可以使用基类的地方使用,因此不能抛出除基类中指定的异常类型之外的任何异常类型。

有三种解决方案:

  1. 修改基类说明符以包含任何子类可能需要抛出的每个异常类型
  2. 修改每个子类以处理除基类
  3. 中指定的异常类型之外的每个异常类型
  4. 删除异常说明符。
  5. 我建议删除它们;他们被广泛认为是一个坏主意,部分是因为这样的问题。正如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