Нарезка std :: out_of_range на std :: exception в Visual Studio против g ++ - PullRequest
2 голосов
/ 08 марта 2019

Я заметил следующее поведение случайно (пропустил отлов по ссылке), но я не смог найти информацию, которая, если бы я знал это заранее, позволила бы мне предсказать это.

При минимальномпример

#include <iostream>
#include <stdexcept>


int main()
{
    try
    {
        // Added this and the next line to check that the exception 
        // created has already the what() set to the input string.
        std::out_of_range d("Out of range exception"); 
        std::cout << "d.what() = " << d.what() << std::endl;
        throw d;
    }
    catch (std::exception e) // Captured by value
    {
        std::cout << e.what() << std::endl;
    }

}

Если я скомпилирую его с g++ -std=c++17 и с Visual C ++, я получу разные варианты поведения.В первом случае он печатает d.what() = Out of range exception\nstd::exception, а во втором - d.what() = Out of range exception\nOut of range exception.

В принципе возможна нарезка, когда std::out_of_range захватывается значением и преобразуется в тип std::exception.Это означает, что я мог ожидать, что при печати what().

я не получу такого же поведения, как объект от объекта std::out_of_range. Вопрос: Часть, которую я не знаю, какобъяснение получает различное поведение для двух компиляторов.Это связано с тем, что в стандартизации C ++ это нарезание является неопределенным поведением или один из этих двух компиляторов не соблюдает его?

Дополнительное наблюдение: Я только что заметил, что в по этой ссылке нет упоминания о классе std::exception, имеющем конструктор, который вводит const char* const &, тогда как на веб-сайте Microsoft они включают его.Мой случайный пример показывает, что они действительно реализовали эти классы по-разному.У меня все еще вопрос, были ли они разрешены (если это поведение не определено) или один из них не соответствует требованиям и какой.

1 Ответ

1 голос
/ 08 марта 2019

Объект все еще нарезается; Вы можете использовать typeid( e ).name(), чтобы распечатать фактический тип, и он отображается как std::exception. Как вы обнаружили, MSVC реализует what() для возврата указателя на строку, для которой установлено std::exception время построения, поэтому оно не теряется, когда исключение out_of_range врезается обратно в базовое исключение.

Per https://en.cppreference.com/w/cpp/error/exception/exception, what () «возвращает строку, определяемую реализацией», поэтому MSVC может сделать это следующим образом.

Чтобы напечатать тип, добавьте его в свой блок catch:

std :: cout << "e.what () =" << e.what () << "Actual type =" << typeid ( e) .name () << std :: endl; </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...