Почему это точное исключение брошено в мой код C ++? - PullRequest
1 голос
/ 01 июля 2019

Я анализирую часть кода, которая была частью моих лекций.Мне удалось скомпилировать его, но я не могу понять: почему моя программа выводит «Wyjatek» и 0 вместо «WyjatekNieoznaczony»?

Я был почти уверен, что WyjatekNieoznaczony () должен быть брошен, потому что a = 0 и b =0 так же.Прямо сейчас я немного смущен.Не могли бы вы помочь мне, пожалуйста?

class Wyjatek {};
class WyjatekBledny : public Wyjatek {};
class WyjatekNieoznaczony : public Wyjatek {};

double f(double a, double b) {
    if (b == 0) {
        if (a == 0)
            throw WyjatekNieoznaczony();
        else
            throw WyjatekBledny();
    }
    return a / b;
}


double g(double a, double b) throw (int) {
    try {
        return f(a, b);
    }
    catch (WyjatekBledny) {
        cout << "Wyjatek bledny" << endl;
        throw 1;
    }
    catch (Wyjatek) {
        cout << "Wyjatek" << endl;
    }
    catch (WyjatekNieoznaczony) {
        cout << "Wyjatek nieoznaczony" << endl;
        throw;
    }
    return 0;
}

int main()
{
    double a = 0, b = 0;
    try {
        cout << g(a, b) << endl;
    }
    catch (...)
    {
        cout << "Inny wyjatek" << endl;
    }
    system("pause");
    return 0;
}

Ответы [ 2 ]

5 голосов
/ 01 июля 2019

Да, действительно, WyjatekNieoznaczony выбрасывается, но на месте улова, catch (Wyjatek) { - это совпадение (из-за наследования), поэтому оно там отлавливается.

Место улова больше похоже на if else блок в поведении - каждая возможность catch рассматривается в том порядке, в котором они написаны, а не switch блок, где вы можете размещать метки в любом порядке.

Обратите внимание такжечто лучше ловить исключения по ссылке const, чем по значению, иначе вы можете столкнуться с ловушками среза объекта .

3 голосов
/ 01 июля 2019

Если вы включили (и прочитали) предупреждения компилятора, вы бы встретили следующую диагностику:

предупреждение: исключение типа 'WyjatekNieoznaczony' будет перехвачено [...] более ранним обработчикомдля 'Wyjatek'.

Это в основном означает, что WyjatekNieoznaczony, наследуя от Wyjatek, будет сначала поймано предложением catch(Wyjatek), поскольку оно конвертируемо.Проблема в том, что из-за нарезки объекта он потеряет Nieoznaczony сущность.

Я предлагаю переупорядочить предложения catch, чтобы была возможностьисчезает нарезка (в данном случае):

catch (WyjatekBledny) {
    cout << "Wyjatek bledny" << endl;
    throw 1;
}
catch (WyjatekNieoznaczony) {
    cout << "Wyjatek nieoznaczony" << endl;
    throw;
}
catch (Wyjatek) {
    cout << "Wyjatek" << endl;
}
...