In an interview I was asked why catching exceptions by value can be a problem and I answered that this can cause object slicing. And this is what I find in the Internet, for example here: https://www.viva64.com/en/w/v746/
But now I am trying to experiment and I cannot find an example of slicing when catching by value. Usual scenario of slicing (not with exceptions) is this:
Derived d1;
Derived d2;
Base& b1 = d1;
Base& b2 = d2;
b1 = b2;
In the last line assignment operator of Base is called, which copies only Base part of Derived object. So Based part of b1 is copied from d2, whilst Derived part of b1 remains from d2. BAD.
But how can this happen when catching exceptions by value?
I tried this code (with both: g++ and Sun CC compilers):
struct Base
{
virtual void print() const
{
cout << "{ Base: " << m << " }" << endl;
}
Base(int _m = 0) : m(_m) {}
int m;
};
struct Derived : Base
{
Derived(int _m = 0, int _n = 0) : Base(_m), n(_n) {}
void print() const
{
cout << "{ Base: " << m << ", Derived: " << n << " }" << endl;
}
int n;
};
int main()
{
try
{
try
{
throw Derived(3, 300);
}
catch(Base x)
{
cout << "Inner catch: ";
x.print();
throw;
}
}
catch(Derived y)
{
cout << "Outer catch: ";
y.print();
}
}
The output was:
Inner catch: { Base: 3 }
Outer catch: { Base: 3, Derived: 300 }
So I throw Derived exception, catch its Base BY VALUE and rethrow, then catch Derived BY VALUE and all works fine, no any slicing. How is that?
And can somebody provide an example of slicing when catching BY VALUE?
Even though
catch(Base)do slice the thrownDerivedobject, the rethrowuses the original exception object instead of the sliced copy.From http://en.cppreference.com/w/cpp/language/throw:
Note that if you replace
throw;bythrow x;, aBaseinstance will be thrown and won't be catch, resulting tostd::abort()to be called. Indeed, the slicedDerivedcannot be unsliced (this is why we generally don't like slices, unless they are pizza slices) to be catched bycatch (Derived).As a conclusion, I'd stick with "Throw by value, catch by (const) reference)". In this specific example you're good with catching by a sliced value, but is is not the case in general. Serge Ballesta's answer provide an example of a catch by value leading to troubles. A quick search on your favorite search engine can help you find other cases where catching by value is looking for troubles.