C++ 一旦捕获,如何从std::exception获取原始异常? //示例程序 #包括 #包括 #包括 无效日志(const std::exception&e){ 试一试{ 投掷e; } 捕获(常量标准::逻辑错误和e1){ std::cout

C++ 一旦捕获,如何从std::exception获取原始异常? //示例程序 #包括 #包括 #包括 无效日志(const std::exception&e){ 试一试{ 投掷e; } 捕获(常量标准::逻辑错误和e1){ std::cout,c++,C++,您可以在log方法中重新显示原始异常,以保持其原始状态。这样,一切都应该按照您的预期工作 修改后的log方法如下所示: // Example program #include <iostream> #include <string> #include <stdexcept> void log(const std::exception& e) { try { throw e; } catch (const std::logic_

您可以在
log
方法中重新显示原始异常,以保持其原始状态。这样,一切都应该按照您的预期工作

修改后的
log
方法如下所示:

// Example program
#include <iostream>
#include <string>
#include <stdexcept>

void log(const std::exception& e) {
  try {
      throw e;
  }
  catch (const std::logic_error& e1) {
      std::cout << "logic_error: " << e1.what() << std::endl; // How to get logic_error back once caught?
  }
  catch (const std::exception& e1) {
      std::cout << "exception: " << e1.what() << std::endl;
  } 
}

int main()
{
  try {
      throw std::logic_error("sth wrong");
  }
  catch (const std::exception& e) {
      log(e);
  }
}
void日志(const std::exception&e){
试一试{
投
}
捕获(常量标准::逻辑错误和e1){
std::cout是
虚拟的
。因此您不需要返回原始类型来写入日志。您只需确保为继承
std::exception
的自定义异常重新定义
what()

这可能成为:

void log(const std::exception& e) {
  try {
      throw;
  }
  catch (const std::logic_error& e1) {
      std::cout << "logic_error: " << e1.what() << std::endl;
  }
  catch (const std::exception& e1) {
      std::cout << "exception: " << e1.what() << std::endl;
  } 
}
void日志(const std::exception&e)
{
std::cout您可以使用:

void日志(std::exception\u ptr eptr){
试一试{
如果(eptr){
std::返回异常(eptr);
}
}
捕获(常量标准::逻辑错误和e1){

std::cout您不必只使用标准库提供的基本异常,您可以使用所需的方法创建自己的异常层次结构

#包括
#包括
#包括
类MyBaseException:public std::exception
{
公众:
虚拟标准::字符串输出()常量=0;
/*在这里定义您需要的方法*/
};
类MySpecificeException:公共MyBaseException
{
公众:
const char*what()const noexcept override{return“error”;}
std::string output()常量重写{return“我想要的特定调试输出”;}
};
int main(){
试一试{
抛出MySpecificException{};
}捕获(常量MyBaseException&e){

std::cout您可以使用运行时类型信息获取执行选项的类型:

void log(std::exception_ptr eptr) {
    try {
        if (eptr) {
            std::rethrow_exception(eptr);
        }
    }
    catch (const std::logic_error& e1) {
        std::cout << "logic_error: " << e1.what() << std::endl;
    }
    catch (const std::exception& e1) {
        std::cout << "exception: " << e1.what() << std::endl;
    }
}

int main()
{
    try {
        throw std::logic_error("sth wrong");
    }
    catch (const std::exception&) { // or even catch (...)
        log(std::current_exception());
    }
}
#包括
#包括
#包括
#包括
#如果定义了(uuu-clang_uuuuuuuu)| |定义了(uu-GNUC_uuuu)
#包括
#恩迪夫
std::string getTypename(const std::exception&e)
{
#如果定义了(uuu-clang_uuuuuuuu)| |定义了(uu-GNUC_uuuu)
//.name()返回gcc和clang上的损坏名称
智力状态;
返回abi::uucxa_demangle(typeid(e).name()、0、0和status);
#否则
//VisualStudio返回一个人类可读的名称
返回typeid(e.name();
#恩迪夫
}
无效日志(const std::exception&e){

std::不能只添加更多带有适当异常类型的
catch
块,这里的问题是什么?“一旦捕获,如何恢复逻辑错误”-你的意思是重播还是什么?@VTT只是增加了更多的描述。这个问题仍然没有意义,你已经抓住了
逻辑错误
。如果你想重播当前的cougt异常,那么你应该只写
throw;
而不是
throw e;
@VTT我认为他(和我)都是忽略的是
throw;
dynamic\u cast
?我需要处理与派生异常相关的更具体的信息,而不仅仅是
what()
信息。@user1633272哦,对不起,您提供的示例只使用了
what()
,我错过了您需要更多的一点,我的错。@user1633272但如果您需要特定的子类成员函数,恐怕您无法避免捕获每个异常,因为从一个调用方法将无法从另一个调用方法,因为它们不共享相同的成员(除了
what()
)。我不想避免捕获每个异常,我只想有一个像
log
这样的单独函数来处理日志逻辑。它将使
main
函数更清晰。@user1633272啊,好的,我以为你想使
log()
函数更清晰。我不明白你刚才说的是
main()
。我知道我可以
在main函数中抛出catch子句。我不知道我以前也可以抛出
log
函数。你的解决方案就是我想要的。你可以去掉不使用的输入参数。而“问题”是
log
只能从catch子句调用(无需编译器检查).一个小问题:通过此更改,不再需要参数
e
void log(std::exception_ptr eptr) {
    try {
        if (eptr) {
            std::rethrow_exception(eptr);
        }
    }
    catch (const std::logic_error& e1) {
        std::cout << "logic_error: " << e1.what() << std::endl;
    }
    catch (const std::exception& e1) {
        std::cout << "exception: " << e1.what() << std::endl;
    }
}

int main()
{
    try {
        throw std::logic_error("sth wrong");
    }
    catch (const std::exception&) { // or even catch (...)
        log(std::current_exception());
    }
}
#include <iostream>
#include <string>
#include <stdexcept>
#include <typeinfo>
#if defined(__clang__) || defined(__GNUC__)
#include <cxxabi.h>
#endif

std::string getTypename(const std::exception& e)
{
    #if defined(__clang__) || defined(__GNUC__)
    // .name() returns a mangled name on gcc and clang
    int status;
    return abi::__cxa_demangle(typeid( e ).name(), 0, 0, &status);
    #else
    // visual studio returns a human readable name
    return typeid( e ).name();
    #endif    
}

void log(const std::exception& e) {
    std::cout << getTypename( e ) << ": " << e.what() << std::endl;
}

int main()
{
  try {
      throw std::logic_error("sth wrong");
  }
  catch (const std::exception& e) {
      log(e);
  }
}