3

我非常喜欢boost::exception,但我很困扰它没有提供适当的开箱即用的what () 函数。现在不要混淆,它确实有一个很好的boost::diagnostic_information包含我想在我的假设what()函数中看到的所有信息,但是因为boost::exception它不会从我得到std::exceptionwhat()函数继承,如果我多重继承(如教程中所建议的) ,请参见下面的行)是基础中的默认无用处what()std::exception它对异常没有任何解释。

struct my_exception: virtual std::exception, virtual boost::exception { };

现在显然我试图覆盖what()并使其返回boost::diagnostic_information,但不知何故它不起作用,所以我有点困惑。那可能是因为它会循环,但我不太确定。

PS:我想what()正确实施的原因是,如果您的程序因它们而死,许多工具默认显示它(例如 gnu 编译器将显示一个很好的致命错误,并显示 what(),增强单元测试工具等.)。

下面是测试代码的链接

#include <boost/exception/all.hpp>

struct my_exception: virtual std::exception, virtual boost::exception {};

struct my_exception2: virtual std::exception, virtual boost::exception {
    virtual const char* what() const throw() {
        return "WHAT";
    }
};

struct my_exception3: virtual std::exception, virtual boost::exception {
    virtual const char* what() const throw() {
        return boost::diagnostic_information(this).c_str();
    }
};

int main() {
    try {
        BOOST_THROW_EXCEPTION(my_exception());
    } catch (const std::exception& e){
        std::cout << e.what() << std::endl; 
        //This is useless ___ std::exception
    }

    try {
        BOOST_THROW_EXCEPTION(my_exception());
    } catch (const boost::exception& e){
        std::cout << boost::diagnostic_information(e) << std::endl; 
        //This is what I'd like to see ___ main.cpp(39): Throw in function int main() ___ Dynamic exception type: boost::exception_detail::clone_impl ___ std::exception::what: std::exception
    }

    try {
        BOOST_THROW_EXCEPTION(my_exception2());
    } catch (const std::exception& e){
        std::cout << e.what() << std::endl; 
        //Overriding what usually works ___ WHAT
    }

    try {
        BOOST_THROW_EXCEPTION(my_exception3());
    } catch (const std::exception& e){
        std::cout << e.what() << std::endl; 
        //But somehow here it does not work ___ Unknown exception.
    }
}
4

2 回答 2

3

首先,boost::diagnostic_information通过 (const) 引用获取异常,并且this是一个指针:

    return boost::diagnostic_information(*this).c_str();
                                         ^-- here

其次,一旦您解决了这个问题,正如您正确预期的那样,这会导致无限递归boost::diagnostic_information调用std::exception::what()。可以使用警卫成员或类似的东西来解决这个问题:

struct my_exception3: std::exception, boost::exception {
    mutable bool in_what = false;
    virtual const char* what() const throw() {
        struct g { bool &b; ~g() { b = false; } } guard{in_what};
        return in_what ? "WHAT" : (in_what = true, boost::diagnostic_information(*this).c_str());
    }
};

最后,您正在使用c_str破坏的临时string. 我将把解决该问题的方法留作练习。

于 2013-05-02T18:16:10.820 回答
1

最终获胜者是...

namespace boost {
    char const * diagnostic_information_what( boost::exception const & e ) throw();
}
于 2013-05-03T08:54:41.497 回答