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?
One other problem of catching Exception by value, it that it requires a full copy of the exception. If you are close to a StackOverflow condition (or already processing one), you could be in a use case where the copy would not be possible, and the catch clause could not be executed.