Opcode
10-09-2010, 12:50
Giorno a tutti,
per gestire varie eccezioni nella mia applicazione ho definito una classe Exception, così dichiarata:
class Exception {
protected:
const char *_message; ///< Contains the error message.
const char *what(); ///< Simply returns the _message content.
public:
/// Base constructor.
Exception(const char *msg): _message(msg) {};
Exception() {};
/**
* Shows the error exploiting the WINAPI MessageBox on Windows.
* On linux prints the message on the standard output.
*/
void show();
/**
* Exactly like Exception::show but it causes the program termination.
* \warning This method causes the program termination!
*/
void fatal();
};
e definita come segue:
const char *Exception::what()
{
return _message;
}
void Exception::show()
{
std::string error(what());
error.append("\n");
error.append("Try reinstalling the application");
MessageBoxA(NULL, error.c_str(), "An error has occurred!", MB_OK);
}
void Exception::fatal()
{
std::string error(what());
error.append("\n");
error.append("Try reinstalling the application");
MessageBoxA(NULL, error.c_str(), "A fatal error has occurred!", MB_OK);
exit(EXIT_FAILURE);
}
Ho definito i metodi Exception::fatal ed Exception::show, sebbene la classe venga ereditata, per evitare di riscrivere in tutte le classi questi due metodi, qualora non ci fosse la necessità di usare qualcosa di diverso.
Ora veniamo al problema.
Ho dichiarato una classe che eredita la classe Exception (chiamata SDLException), in questa classe mi serve dichiarare anche nuovi metodi fatal ed exception perchè devono andare a recuperare il valore _message di SDLException, non quello della classe da cui ereditano, poichè non esistono overload del costruttore della classe Exception per accettare l'errore in questione.
Quindi diciamo, il principio è quello di ereditare dalla classe Exception per poter catturare l'eccezione in modo generico, ma poi chiamare il metodo "fatal" di SDLException, non quello di Exception.
Ecco la dichiarazione, seguita dalla definizione:
class SDLException: public Exception {
private:
char *_message;
const char *what();
public:
/// \param message the error message
/// \param SDLError if true describes the SDL error
SDLException(const char *message, bool SDLError);
void fatal();
void show();
};
SDLException::SDLException(const char *message, bool SDLError):
Exception(message)
{
string errorMsg(message);
if (SDLError) {
errorMsg.append("\n");
errorMsg.append(SDL_GetError());
}
_message = new char[errorMsg.size()];
errorMsg.copy(_message, errorMsg.size());
}
const char *SDLException::what()
{
return _message;
}
void SDLException::show()
{
std::string error(what());
error.append("\n");
error.append("Maybe reinstalling the game could fix this issue");
MessageBoxA(NULL, error.c_str(), "An error has occurred!", MB_OK);
}
void SDLException::fatal()
{
std::string error(what());
error.append("\n");
error.append("Maybe reinstalling the game could fix this issue");
MessageBoxA(NULL, error.c_str(), "A fatal error has occurred!", MB_OK);
exit(EXIT_FAILURE);
}
Qui i problemi sono due:
- Se non uso il costruttore Exception che accetta il messaggio come parametro (Exception::Exception(const char *), addirittura mi crasha il programma per eccezione non gestita.
- Se invece (come nella definizione precedente) passo il parametro Exception(message), l'eccezione viene gestita, ma qui:
catch (Exception &ex) {
ex.fatal();
return 0;
}
Viene chiamato il metodo Exception::fatal() non il metodo SDLException::fatal().
Ricordo che la differenza tra i due è semplicemente il messaggio che vanno a prendere, SDLException prende un messaggio costruito anche con l'errore specifico della libreria esterna (SDLException::_message), mentre Exception::fatal() no (Exception::_message).
Come potrei risolvere (magari ambedue i problemi)?
Se ritenete inadatta la corrente implementazione, sono accette anche proposte per implementazioni differenti :)
Se non sono stato chiaro chiedete pure, rispondo appena possibile.
Grazie, buona giornata.
per gestire varie eccezioni nella mia applicazione ho definito una classe Exception, così dichiarata:
class Exception {
protected:
const char *_message; ///< Contains the error message.
const char *what(); ///< Simply returns the _message content.
public:
/// Base constructor.
Exception(const char *msg): _message(msg) {};
Exception() {};
/**
* Shows the error exploiting the WINAPI MessageBox on Windows.
* On linux prints the message on the standard output.
*/
void show();
/**
* Exactly like Exception::show but it causes the program termination.
* \warning This method causes the program termination!
*/
void fatal();
};
e definita come segue:
const char *Exception::what()
{
return _message;
}
void Exception::show()
{
std::string error(what());
error.append("\n");
error.append("Try reinstalling the application");
MessageBoxA(NULL, error.c_str(), "An error has occurred!", MB_OK);
}
void Exception::fatal()
{
std::string error(what());
error.append("\n");
error.append("Try reinstalling the application");
MessageBoxA(NULL, error.c_str(), "A fatal error has occurred!", MB_OK);
exit(EXIT_FAILURE);
}
Ho definito i metodi Exception::fatal ed Exception::show, sebbene la classe venga ereditata, per evitare di riscrivere in tutte le classi questi due metodi, qualora non ci fosse la necessità di usare qualcosa di diverso.
Ora veniamo al problema.
Ho dichiarato una classe che eredita la classe Exception (chiamata SDLException), in questa classe mi serve dichiarare anche nuovi metodi fatal ed exception perchè devono andare a recuperare il valore _message di SDLException, non quello della classe da cui ereditano, poichè non esistono overload del costruttore della classe Exception per accettare l'errore in questione.
Quindi diciamo, il principio è quello di ereditare dalla classe Exception per poter catturare l'eccezione in modo generico, ma poi chiamare il metodo "fatal" di SDLException, non quello di Exception.
Ecco la dichiarazione, seguita dalla definizione:
class SDLException: public Exception {
private:
char *_message;
const char *what();
public:
/// \param message the error message
/// \param SDLError if true describes the SDL error
SDLException(const char *message, bool SDLError);
void fatal();
void show();
};
SDLException::SDLException(const char *message, bool SDLError):
Exception(message)
{
string errorMsg(message);
if (SDLError) {
errorMsg.append("\n");
errorMsg.append(SDL_GetError());
}
_message = new char[errorMsg.size()];
errorMsg.copy(_message, errorMsg.size());
}
const char *SDLException::what()
{
return _message;
}
void SDLException::show()
{
std::string error(what());
error.append("\n");
error.append("Maybe reinstalling the game could fix this issue");
MessageBoxA(NULL, error.c_str(), "An error has occurred!", MB_OK);
}
void SDLException::fatal()
{
std::string error(what());
error.append("\n");
error.append("Maybe reinstalling the game could fix this issue");
MessageBoxA(NULL, error.c_str(), "A fatal error has occurred!", MB_OK);
exit(EXIT_FAILURE);
}
Qui i problemi sono due:
- Se non uso il costruttore Exception che accetta il messaggio come parametro (Exception::Exception(const char *), addirittura mi crasha il programma per eccezione non gestita.
- Se invece (come nella definizione precedente) passo il parametro Exception(message), l'eccezione viene gestita, ma qui:
catch (Exception &ex) {
ex.fatal();
return 0;
}
Viene chiamato il metodo Exception::fatal() non il metodo SDLException::fatal().
Ricordo che la differenza tra i due è semplicemente il messaggio che vanno a prendere, SDLException prende un messaggio costruito anche con l'errore specifico della libreria esterna (SDLException::_message), mentre Exception::fatal() no (Exception::_message).
Come potrei risolvere (magari ambedue i problemi)?
Se ritenete inadatta la corrente implementazione, sono accette anche proposte per implementazioni differenti :)
Se non sono stato chiaro chiedete pure, rispondo appena possibile.
Grazie, buona giornata.