打印类的初始化函数的名称

时间:2014-12-01 00:32:31

标签: c++ exception-handling

是否可以捕获并打印初始化类对象的函数名称?我想要的是这样的:

class MyException: public std::exception
{
public:
    MyException(const std::string message, const std::string caller = __func__)
        : _caller(caller),
          _msg(message)
    {
            ...
    }

    std::string what(void); // prints messaged along with the caller
private:
    ...
}

在上面的类MyException中,我希望调用者捕获实例化对象的函数名,以便警告用户抛出了哪个函数。我总能做到

  ...
  throw MyException(message, __func__);
  ...
删除默认__func__

。但是每当我实例化一个MyException对象时,我就会做这个微不足道的事情。

有没有更好的方法来指导用户究竟抛出哪个函数?

提前致谢,

尼基尔

1 个答案:

答案 0 :(得分:0)

如果我想为我的例外提供自动上下文,我可以这样做:

#include <iostream>
#include <stdexcept>
#include <string>

struct context_info {
    explicit context_info(std::string function)
    : _function { std::move(function) }
    {}

    // perhaps the context info will increase later to include class and instance?  
    friend std::string to_string(const context_info& ci)
    {
        return ci._function;
    }

private:
    std::string _function;
};

struct my_exception : std::runtime_error
{
    my_exception(const std::string& message)
    : std::runtime_error(message)
    {}

    my_exception(context_info context, const std::string& message)
    : my_exception(message + " called from " + to_string(context))
    {}

    // everything else already taken care of for you
};

#if defined(NDEBUG)
  #define THROW_WITH_CONTEXT(TYPE, ...) throw TYPE(__VA_ARGS__)
#else
  #define THROW_WITH_CONTEXT(TYPE, ...) throw TYPE(context_info(__func__), __VA_ARGS__)
#endif

using namespace std;

void do_foo()
try {
    THROW_WITH_CONTEXT(my_exception, "foo failure");
}
catch(const exception& e) {
    cout << e.what() << endl;
}

int main() {
    // your code goes here
    try {
        do_foo();
        THROW_WITH_CONTEXT(my_exception, "error");
    }
    catch(const exception& e) {
        cout << e.what() << endl;
    }
    return 0;
}

预期产出:

foo failure called from do_foo
error called from main

然而,整洁,因为它可能不是你应该做的,因为它不会在大型复杂程序中为你提供足够的上下文。

查看std::throw_with_nested等文档。您可以在调用堆栈的每个阶段捕获异常,并使用其他上下文信息重新抛出异常。这更有用。

http://en.cppreference.com/w/cpp/error/throw_with_nested