S.Rucinski
S.Rucinski

Reputation: 99

Why is this exact exception thrown in my c++ code?

I am analyzing part of code that was part of my lectures. I have managed to compile it but I cannot understand: why does my program output "Wyjatek" and 0 instead of "WyjatekNieoznaczony"?

I was pretty sure WyjatekNieoznaczony() should be thrown because a=0 and b=0 as well. Right now i am a little bit confused. Could you help me, please?

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;
}

Upvotes: 0

Views: 168

Answers (2)

Fureeish
Fureeish

Reputation: 13424

If you enabled (and read) compiler warnings, you would've encountered the following diagnostic:

warning: exception of type 'WyjatekNieoznaczony' will be caught [...] by earlier handler for 'Wyjatek'.

This basically means that WyjatekNieoznaczony, by inheriting from Wyjatek, will be first caught by catch(Wyjatek) clause, since it's convertible. The problem is that due to object slicing, it will lose its Nieoznaczonyness.

What I suggest is to reorder the catch clauses so the possibility of slicing disappears (in this case):

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

Upvotes: 3

Bathsheba
Bathsheba

Reputation: 234665

Yes indeed a WyjatekNieoznaczony is thrown, but at the catch site, catch (Wyjatek) { is a match (due to the inheritance) so it's caught there.

A catch site is more like an if else block in behaviour - with each catch possibility being considered in the order they are written - rather than a switch block where you can put the labels in any order you like.

Note also that it's a good idea to catch exceptions by const reference than by value, else you can suffer the pitfalls of object slicing.

Upvotes: 4

Related Questions