1

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;
}
Meraj al Maksud
  • 1,528
  • 2
  • 22
  • 36
S.Rucinski
  • 109
  • 1
  • 8
  • 2
    `catch` statements work from top to bottom. If an exception can be caught by a given `catch`, it will be and the rest of them will be ignored. Since `WyjątekNieoznaczony` is also a `Wyjatek`, only the second catch will be executed. I'm looking for a duplicate of this. – Yksisarvinen Jul 01 '19 at 12:15
  • 1
    Closest question to yours I could find https://stackoverflow.com/questions/29731033/why-base-class-catch-block-catch-derived-class-object – StoryTeller - Unslander Monica Jul 01 '19 at 12:15
  • 1
    Possible duplicate of [C++ exception handling in class hierarchies](https://stackoverflow.com/questions/5575307/c-exception-handling-in-class-hierarchies) – Yksisarvinen Jul 01 '19 at 12:16
  • 2
    A side note: coding in English is a good practice. It will help you a lot later, when for example you need to ask another question on StackOverflow. Not all of us know Polish ;) – Yksisarvinen Jul 01 '19 at 12:20
  • I will keep that in mind while posting in the future :) – S.Rucinski Jul 01 '19 at 12:27
  • 1
    Please add proper indentation to your post so that we can easily follow your code. – Lightness Races in Orbit Jul 01 '19 at 15:59
  • @Yksisarvinen Close as dupe or don't close as dupe but please do not give the answer in the comments section. Thank you – Lightness Races in Orbit Jul 01 '19 at 16:00

2 Answers2

5

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.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    Thank you very much! This code was supposed to be tricky for students I guess. I will keep your advice at mind! – S.Rucinski Jul 01 '19 at 12:37
  • Catching by value also defeats the purpose of memory being reserved for exceptions ahead of time (though that's not particularly important unless the exception you catch was thrown due to a memory shortage). Or ... is such a copy elided? Hmm – Lightness Races in Orbit Jul 01 '19 at 15:59
3

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;
}
Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • Thank you very much! Now I am aware that I was caused by inheritance and I understand it. – S.Rucinski Jul 01 '19 at 12:21
  • @SzymonRuciński, no problem! However I advise you to look into [Bathsheba's answer](https://stackoverflow.com/a/56835518/7151494) too and apply the `catch`ing by `const&` rather than by value. Furthermore, if the answer solved your issue, I suggest accepting it so the future visitors will know that it indeed is the solution. – Fureeish Jul 01 '19 at 12:28