捕获异常后确定异常类型?

Bri*_*ndy 40 c++ exception-handling exception

有没有办法确定异常类型,甚至知道你抓住了异常捕获所有?

例:

try
{
   SomeBigFunction();
}
catch(...)
{
   //Determine exception type here
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ork 31

简答:没有.

答案很长:

如果从公共基类型(例如std :: exception)派生所有异常并明确捕获它,则可以使用它来从异常中获取类型信息.

但是你应该使用catch的特性来捕获特定类型的异常,然后从那里开始工作.

catch(...)唯一真正的用途是:

  • Catch:并抛弃异常(停止异常转义析构函数).
  • Catch:记录一个unknwon异常事件并重新抛出.

编辑:你可以通过dynamic_cast <>()或通过typid()提取类型信息虽然如上所述这不是我推荐的东西.使用案例陈述.

#include <stdexcept>
#include <iostream>

class X: public std::runtime_error  // I use runtime_error a lot
{                                   // its derived from std::exception
    public:                         // And has an implementation of what()
        X(std::string const& msg):
            runtime_error(msg)
        {}
};

int main()
{
    try
    {
        throw X("Test");
    }
    catch(std::exception const& e)
    {
        std::cout << "Message: " << e.what() << "\n";

        /*
         * Note this is platform/compiler specific
         * Your milage may very
         */
        std::cout << "Type:    " << typeid(e).name() << "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 24

你可以在catch(...)中实际确定类型,但它不是很有用:

#include <iostream>
#include <exception>

    class E1 : public std::exception {};
    class E2 : public std::exception {};

    int main() {
        try {
            throw E2();
        }
        catch( ... ) {
            try {
                throw;
            }
            catch( const E1 & e ) {
                std::cout << "E1\n";
            }
            catch( const E2 & e ) {
                std::cout << "E2\n";
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果`try {throw; }`part是在`catch(...)`块中调用的函数. (5认同)
  • 这种技术*非常有用.想想在`catch(...)`中调用异常处理程序.异常处理程序使用此技术重新抛出并确定类型.这允许将正常代码路径与异常(异常)代码路径分开. (3认同)

use*_*683 12

没有标准的,便携的方式来做到这一点.这是在GCC和clang上执行此操作的非便携方式

#include <iostream>
#include <cxxabi.h>

const char* currentExceptionTypeName()
{
    int status;
    return abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &status);
}

int main()
{
    try {
        throw std::string();
    } catch (...) {
        std::cout<<"Type of caught exception is "<<currentExceptionTypeName()<<std::endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Type of caught exception is std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您应该 free() 从 __cxa_demangle 返回的指针,否则您将泄漏内存。此外,最好检查返回值是否不为空(在内存不足的情况下捕获 std::bad_alloc 时可能会发生这种情况)。 (2认同)

use*_*449 7

前提是 c++11 可用,

bool throwing_func()
{
    // something is wrong...
    throw char('5');

    // ...

    return true;
}

void exception_handler(std::exception_ptr _Eptr)
{
    try 
    {
        if (_Eptr) {std::rethrow_exception(_Eptr);}
    }


    catch(int _Xi)
    {
        std::cout << "int\n";
    }

    catch(char _Xc)
    {
        std::cout << "char\n";
    }

    catch(const std::exception& _Xe)
    {
       std::cout << "std::exception " << _Xe.what() << "\n";
    }

    catch (...)
    {// develop more catch cases above to avoid what follows
        std::cout << "unhandled exception\n";
        // grande problema
    }
}

int main()
{

    try
    {
        throwing_func();
    }

    catch(...)
    {
        //Determine exception type here

         exception_handler(std::current_exception());
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Har*_*lby 6

如果您需要根据它们的不同来处理异常,那么您应该捕获特定的异常.如果存在所有需要以相同方式处理的异常组,则从公共基类派生它们并捕获基类将是可行的方法.利用语言的力量和范例,不要与他们作斗争!