我正在使用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方法变为虚拟,但是在每个异常中使用正确的返回类型声明它。它有效,但它并不漂亮。
答案 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!