Содержимое строки 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 не страдает от этой проблемы.
Вы получаете этот вывод, потому что в первом случае вы создаете новый 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 ++ реализует
что (), сохраняя текст сообщения в базовом классе исключений. Другой
реализации не делают.
Других решений пока нет …