Using RTTI to implement a robust error handling system can provide detailed type information, making debugging and error tracking more effective.
Here's an approach to create such a system. First, create a base Exception
class:
#include <stdexcept>
#include <string>
#include <typeinfo>
class Exception : public std::runtime_error {
public:
Exception(const std::string& message)
: std::runtime_error(message) {}
virtual std::string getTypeName() const {
return typeid(*this).name();
}
};
Implement specific exception types:
#include <stdexcept>
#include <string>
#include <typeinfo>
class Exception : public std::runtime_error {/*...*/};
class NetworkException : public Exception {
public:
NetworkException(const std::string& message)
: Exception(message) {}
};
class DatabaseException : public Exception {
public:
DatabaseException(const std::string& message)
: Exception(message) {}
};
Create an error handling function that uses RTTI:
#include <iostream>
#include <stdexcept>
#include <string>
#include <typeinfo>
class Exception : public std::runtime_error {/*...*/};
class NetworkException : public Exception {/*...*/};
class DatabaseException : public Exception {/*...*/};
void handleException(const Exception& e) {
std::cout << "Exception type: "
<< e.getTypeName() << '\n';
std::cout << "Error message: "
<< e.what() << '\n';
if (typeid(e) == typeid(NetworkException)) {
std::cout
<< "Network-specific error handling...\n";
} else if (typeid(e) == typeid(DatabaseException)) {
std::cout
<< "Database-specific error handling...\n";
} else {
std::cout
<< "Generic error handling...\n";
}
}
Use the error handling system:
#include <iostream>
#include <stdexcept>
#include <string>
#include <typeinfo>
class Exception : public std::runtime_error {/*...*/};
class NetworkException : public Exception {/*...*/};
class DatabaseException : public Exception {/*...*/};
void handleException(Exception&) {/*...*/}
void simulateError(int errorType) {
if (errorType == 1) {
throw NetworkException("Connection failed");
} else if (errorType == 2) {
throw DatabaseException("Query execution failed");
} else {
throw Exception("Unknown error");
}
}
int main() {
for (int i = 0; i < 3; ++i) {
try {
simulateError(i);
} catch (const Exception& e) {
handleException(e);
std::cout << "-------------------\n";
}
}
}
Exception type: class Exception
Error message: Unknown error
Generic error handling...
-------------------
Exception type: class NetworkException
Error message: Connection failed
Network-specific error handling...
-------------------
Exception type: class DatabaseException
Error message: Query execution failed
Database-specific error handling...
-------------------
This system provides several benefits:
getTypeName()
method uses RTTI to provide the exact type of the exception.handleException()
function uses typeid
to perform type-specific error handling.Exception
.To make this system even more robust, you could:
Remember that while RTTI provides powerful capabilities, it does come with a small runtime cost. In most cases, this cost is negligible compared to the benefits of detailed error information, but it's something to keep in mind for performance-critical systems.
Answers to questions are automatically generated and may not have been reviewed.
typeid()
Learn to identify and react to object types at runtime using RTTI, dynamic casting and the typeid()
operator