std :: exception.what () возвращает неожиданное значение для clang и gcc, но не для VS11

Содержимое строки C, возвращаемой функцией std :: exception.what () и ее производными классами, определяется реализацией, но 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 реализуют исключение :: что () что-то вроде

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

и что все производные классы используют эту реализацию метода what (). Если я заменю e.what () с TypeId (е) .name () в приведенном выше коде, то выход Clang и GCC

St9exception
St9bad_alloc

и выходы VS11

class std::exception
class std::bad_alloc

Я не понимаю, почему typeid не является std :: bad_alloc для обоих блоков catch. Такое поведение приводит к тому, что метод what () возвращает неправильное значение. Microsoft, должно быть, создала разные, тривиальные реализации what () для всех классов, производных от std :: exception, поэтому VS11 не страдает от этой проблемы.

2

Решение

Вы получаете этот вывод, потому что в первом случае вы создаете новый 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:

Различное сообщение в случае OP заключается в том, что VC ++ реализует
что (), сохраняя текст сообщения в базовом классе исключений. Другой
реализации не делают.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]