【问题标题】:Converting exception types in c++在 C++ 中转换异常类型
【发布时间】:2021-05-18 04:27:49
【问题描述】:

我有一些看起来像这样的例外

class ExceptionType1Base : public std::runtime_error {

};

class ExceptionType1Derived1 : public ExceptionType1Base {

};

class ExceptionType1Derived2 : public ExceptionType1Base {

};

还有另一种异常类型

class ExceptionType2Base : public std::runtime_error {
   public:
    int type;
};

class ExceptionType2Derived1 : public ExceptionType2Base {
    ExceptionType2Derived1() {
       type = 1;
    }  

};

class ExceptionType2Derived2 : public ExceptionType2Base {
    ExceptionType2Derived2() {
       type = 2;
    }  
};

我想在捕获时将一种异常类型转换为另一种类型,例如

ExceptionType1Base convertToType1Exception(ExceptionType2Base& ex) {
     if(ex.type == 1) {
        return ExceptionType1Derived1();
     }

     return ExceptionType1Derived2();
}

然后当我捕获异常时,它会像

try {
    ... some code .... 
} catch (const ExceptionType2Base& ex) {
    throw convertToType1Exception(ex);
}

问题是我丢失了转换后异常的派生类型,而最终抛出的异常是 ExceptionType1Base,有更好的处理方法吗?我想过使用宏进行异常类型转换,但我想知道是否有更好的方法。

【问题讨论】:

  • ExceptionType1Base convertToType1Exception() -> 请寻找对象切片。你的函数convertToType1Exception() 总是返回一个ExceptionType1Base 的实例。 (隐式转换发生在每个returns 中。因此,除了ExceptionType1Base 之外,您永远无法捕捉到其他东西。
  • 您正在寻找两个对象之间的一对一映射。我认为即使使用模板,您也无法在逻辑上确定函数的返回类型(在这里满足您的要求)。您可以在单独的 catch 块中捕获两个 type1 对象并抛出相应的 type2 对象。只要您没有大量此类映射,这应该可以扩展。
  • 感谢您提供详细信息。所以如果我想实现这样的用例。想象一下 10 个不同的异常,这个方法需要在很多地方调用。你将如何实现它?
  • @MikeLoury 检查此onlinegdb.com/iz0dtRp5n

标签: c++ exception c++17


【解决方案1】:

您想实现ExceptionType1ExceptionType2 之间的映射。您当前的实现不起作用,因为根据convertToType1Exception 的签名,它将始终返回ExceptionType1Base 对象。但请注意,返回对象的 type 属性将是 1 或 2,具体取决于它是 ExceptionType1Derived1 还是 ExceptionType1Derived2

解决此问题的一种方法是单独捕获 Type1 异常并抛出相应的 Type2 异常。以下是执行此操作的示例。您可以通过添加更多 catch 案例来扩展它以处理更多异常。

#include <iostream>
#include <typeinfo>

class ExceptionType1Base
{
};
class ExceptionType1Derived1:public ExceptionType1Base
{
};
class ExceptionType1Derived2:public ExceptionType1Base
{
};

class ExceptionType2Base
{
public:
  ExceptionType2Base ()
  {
  }
  int type;
};

class ExceptionType2Derived1:public ExceptionType2Base
{
public:
  ExceptionType2Derived1 ()
  {
    type = 1;
  }
};
class ExceptionType2Derived2:public ExceptionType2Base
{
public:
  ExceptionType2Derived2 ()
  {
    type = 2;
  }
};

ExceptionType1Derived1
t1d1 ()
{
  throw ExceptionType1Derived1 ();
}

ExceptionType1Derived2
t1d2 ()
{
  throw ExceptionType1Derived2 ();
}

int
main ()
{
  try
  {
    t1d2 ();
    //t1d1();
  } catch (const ExceptionType1Derived1 & ex)
  {
    throw ExceptionType2Derived1 ();
  } catch (const ExceptionType1Derived2 & ex)
  {
    throw ExceptionType2Derived2 ();
  }
  return 0;
}

这里 main 将抛出 ExceptionType2Derived2。如果你打电话给t1d1,那么ExceptionType1Derived1

【讨论】:

  • 这可行,但我唯一的问题是,如果您必须跨 20 个方法和 10 个异常执行此操作,那就太多了。我最终没有使用 convert 而只是定义了一个新方法: throwMappedException() 并让这个方法抛出而不是返回一个对象。看起来这里没有完美的解决方案。
猜你喜欢
  • 2016-01-16
  • 2021-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-17
  • 2013-01-30
  • 1970-01-01
相关资源
最近更新 更多