Rule A15-3-5 (required, implementation, automated)
A class type exception shall be caught by reference or const reference.
Rationale
If a class type exception object is caught by value, slicing occurs. That is, if the exception object is of a derived class and is caught as the base, only the base class’s functions (including virtual functions) can be called. Also, any additional member data in the derived class cannot be accessed. If the exception is caught by reference or const reference, slicing does not occur.
Example
//% $Id: A15-3-5.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#include <iostream>
#include <stdexcept>
class Exception : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
const char* what() const noexcept(true) override
{
return "Exception error message";
}
};
void Fn()
{
try
{
// ...
throw std::runtime_error("Error");
// ...
throw Exception("Error");
}
catch (const std::logic_error& e) // Compliant - caught by const reference
{
// Handle exception
}
catch (std::runtime_error& e) // Compliant - caught by reference
{
std::cout << e.what() << "\n"; // "Error" or "Exception error message"
// will be printed, depending upon the
// actual type of thrown object
throw e; // The exception re-thrown is of its original type
}
catch (
std::runtime_error
e)
// Non-compliant - derived types will be caught as the base type
{
std::cout
<< e.what()
<< "\n"; // Will always call what() method from std::runtime_error
throw e; // The exception re-thrown is of the std::runtime_error type,
// not the original exception type
}
}
See also
MISRA C++ 2008 [7]: 15-3-5 A class type exception shall always be caught by reference. SEI CERT C++ [10]: ERR61-CPP. Catch exceptions by lvalue reference
C++ Core Guidelines [11]: E.15: Catch exceptions from a hierarchy by reference