2

std::exception.what() 及其派生类返回的 C 字符串的内容是实现定义的,但 clang、gcc 和 Visual Studio 返回指示异常类名称的 C 字符串。但是当我在 clang 3.2、gcc 4.7 和 Visual Studio 2012 上运行以下代码时,我得到了奇怪的结果:

#include <iostream>
#include <exception>

int main(int argc, const char * argv[])
{
    try {
        throw std::bad_alloc();
    } catch (std::exception e) {
        std::cout << e.what() << std::endl;
    }

    try {
        throw std::bad_alloc();
    } catch (std::bad_alloc e) {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

使用 clang 和 gcc 的输出是

std::exception
std::bad_alloc

VS11的输出是

bad allocation
bad allocation

我的理解是 clang 和 gcc 实现了 exception::what() 类似的东西

const char* exception::what() const
{
    return __typename_demangle(typeid(*this).name());
}

并且所有派生类都使用 what() 方法的这种实现。如果我在上面的代码中将 e.what()替换为typeid(e).name()则 clang 和 gcc 输出

St9exception
St9bad_alloc

和 VS11 输出

class std::exception
class std::bad_alloc

我不明白为什么两个 catch 块的 typeid 都不是 std::bad_alloc 。这种行为似乎会导致 what() 方法返回错误的值。Microsoft 必须为从 std::exception 派生的所有类创建了不同的、简单的 what() 实现,因此 VS11 不会遇到这个问题。

4

1 回答 1

3

你得到这个输出是因为在第一种情况下你创建了一个新std::exception对象,而在第二种情况下 - 新std::bad_alloc对象。相反,您应该通过引用捕获异常。以下代码应显示差异:

#include <iostream>
#include <string>

class Foo
{
public:
    Foo()
    {
        // std::cout << "Foo()" << std::endl;
    }

    Foo(const Foo&)
    {
        std::cout << "Foo(const Foo&)" << std::endl;
    }

    virtual ~Foo()
    {

    }

    virtual std::string what() const
    {
        return "what: Foo";
    }
};

class Bar: public Foo
{
public:
    Bar()
    {
        // std::cout << "Bar()" << std::endl;
    }

    Bar(const Bar&)
    {
        std::cout << "Bar(const Bar&)" << std::endl;
    }

    std::string what() const
    {
        return "what: Bar";
    }
};

int main()
{
    try
    {
        throw Bar();
    }
    catch(Foo f)
    {
        std::cout << f.what() << std::endl;
    }

    try
    {
        throw Bar();
    }
    catch(const Foo& f)
    {
        std::cout << f.what() << std::endl;
    }

    return 0;
}

输出是

Foo(const Foo&)
what: Foo
what: Bar

但是我没有VS11,所以我不能告诉你,为什么VS会产生这样的输出。如果有人能澄清这一点,那就太好了。

感谢@BoPersson:

The different message in the OP's case is because VC++ implements what() by storing the message text in the exception base class. Other implementations do not.

于 2013-03-30T08:10:35.677 回答