返回基类类型的引用时捕获派生异常?

时间:2010-08-20 14:44:40

标签: c++ polymorphism

我正在使用C ++编写Windows应用程序,并在处理异常时遇到以下问题。

我有一个基本异常类,所有其他异常都来自该异常类。在基类中,我有一个任何异常的错误消息的方法。然后该方法返回异常(通过'* this')。

现在,当我想扩展派生异常并稍后在catch块中使用它时,会出现问题。由于extend方法是在基类中声明的,因此catch块捕获基类而不是派生类。有没有办法解决这个问题,以便找到正确的派生类?

以下是一些说明问题的代码:


// DECLARATIONS

class BaseException {
    BaseException() { }

    Exception& extend( string message ) {
        // extend message

        return *this;
    }
}

class DerivedException : public BaseException {
    DerivedException() : Exception() { }
}



// RUNNING CODE

int main() {
    try {
         ...

         try {
             ...

             // Something goes wrong
             throw DerivedException( "message1" );
         }
         catch ( DerivedException& exc ) {
             throw exc.extend( "message2" );
         }
    }
    catch ( DerivedException& ) {
        // Here is where I *want* to land
    }
    }
    catch ( BaseException& ) {
        // Here is where I *do* land
    }
}

目前我已经通过而不是“解决”了它,使得extend方法变为虚拟,但是在每个异常中使用正确的返回类型声明它。它有效,但它并不漂亮。

4 个答案:

答案 0 :(得分:5)

分离extend()调用和重新抛出异常会更简单:

 catch ( DerivedException& exc ) {
     exc.extend( "message2" );
     throw;
 }

这种方式extend()不必返回任何内容,并且始终会抛出/捕获正确的异常。

答案 1 :(得分:0)

问题是extend的返回类型是'BaseException&'。因此'throw exc.extend()'被错误的异常处理程序捕获。

如果要抛出相同的异常,请使用空抛;声明。 OP代码有很多错误。

class BaseException {
public:
    BaseException() { } 

    BaseException& extend( string message ) { 
        // extend message 

        return *this; 
    } 
}; 

class DerivedException : public BaseException { 
public:
    DerivedException() : BaseException() { } 
}; 



// RUNNING CODE 

int main() { 
   try { 

      try { 
         // Something goes wrong 
         throw DerivedException(); 
      } 
      catch ( DerivedException& exc ) { 
         throw exc.extend("A"); 
      } 
   } 
   catch ( DerivedException& ) { 
      // Here is where I *want* to land 
      int i = 0;
   } 
   catch ( BaseException& ) { 
      // Here is where I *do* land 
      int i = 0;
   }
}

答案 2 :(得分:0)

可以使用“Curiously recurring template pattern

来完成
template <typename TExc>
class BaseException { 
    BaseException() { } 

    TExc& extend( string message ) { 
        // extend message 

        return (TExc) *this; 
    } 
} 

class DerivedException : public BaseException<DerivedException> { 
    DerivedException() : BaseException() { } 
}

答案 3 :(得分:0)

你应该将extend函数设为virtual,并返回DerivedException&amp;在DerivedException的覆盖中。这对于可以隐式转换返回值的特殊情况是合法的 - 例如原始函数签名返回覆盖函数签名的返回值的基类,如下所示。

class BaseException {
public:
    BaseException() { }

    virtual BaseException& extend( std::string message ) {
        // extend message

        return *this;
    }
};

class DerivedException : public BaseException {
public:
    virtual DerivedException& extend( std::string message ) {
        return *this;
    }
    DerivedException(std::string) : BaseException() { }
};



// RUNNING CODE

int main() {
    try {
         try {
             // Something goes wrong
             throw DerivedException( "message1" );
         }
         catch ( DerivedException& exc ) {
             throw exc.extend( "message2" );
         }
    }
    catch ( DerivedException& ) {
        std::cout << "DerivedException!";
    }
    catch ( BaseException& ) {
        std::cout << "BaseException!";
    }
    std::cin.get();
}

显示DerivedException!