|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
|
[C++] Problema ereditando da una classe
Giorno a tutti,
per gestire varie eccezioni nella mia applicazione ho definito una classe Exception, così dichiarata: Codice:
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();
};
Codice:
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);
}
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: Codice:
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();
};
Codice:
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);
}
- 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: Codice:
catch (Exception &ex) {
ex.fatal();
return 0;
}
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.
__________________
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
La classe Exception non ha i metodi dichiarati come virtual.
Ma non capisco perchè mai ridichiarare _message (tra l'altro come char*) quando è già protected in Exception? E ancora perchè non fai derivare Exception da std::exception? Infine non è proprio bello che un'eccezione spari fuori un messagebox. |
|
|
|
|
|
#3 | ||||
|
Member
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
|
Anzitutto grazie della risposta. Mi hai aiutato a fixare il problema.
Quote:
Quote:
Quote:
Non vedo cosa mi possa offrire in più il derivare da std::exception la mia classe Exception. Sicuramente mi sbaglio, magari potrai illuminarmi. Non mi costa nulla farla derivare da quella eccezione. Quote:
Grazie ancora.
__________________
|
||||
|
|
|
|
|
#4 | ||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Infine, giusto prendendo spunto da i linguaggi che sono venuti dopo, male non fa derivare le eccezioni da quelle della libreria standard, qualcuno potrebbe avere nel codice un catch(const std::exception & ex) e riuscre a catturare la tua eccezione riuscendo a leggerne il messaggio d'errore. Quote:
Se volessi utilizzare le tue classi per gestire eccezioni interne non necessariamente da mostrare all'utente? Infine, forse nell'immediato più importante di tutte le pippe mentali riguardo alla corretta scrittura del codice, non passando l'HWND del parent al messagebox (che nel contesto dell'eccezione ovviamente non hai) l'utente potrebbe non accorgersi del messagebox in quanto potrebbe rimanere nascosto dall'interfaccia del programma, non risultando quindi bloccante. In tal caso l'utente continuerebbe ad utilizzare il programma in condizioni potenzialmente instabili. |
||
|
|
|
|
|
#5 | |||
|
Member
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
|
Perdona la mia ignoranza, se sbaglio correggimi, ma la classe std::exception definisce exception::what() come:
Codice:
virtual const char* what() const throw(); Codice:
class exception {
public:
exception () throw();
exception (const exception&) throw();
exception& operator= (const exception&) throw();
virtual ~exception() throw();
virtual const char* what() const throw();
}
Quote:
Quote:
Quote:
__________________
|
|||
|
|
|
|
|
#6 | |||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Nel mio caso non è stato necessario avere nessun campo stringa aggiuntivo e tutta l'informazione è recuperabile tramite il what di exception. Magari non è esattamente il tuo caso, in ogni caso basta una variabile stringa di appoggio e ridefinire what() nella tua classe. Io comunque ti consiglio di abbandonare l'utilizzo di stringhe C e utilizzare solamente std::string troppo più comode e soprattutto molto più sicure da utilizzare. Quote:
Quote:
|
|||
|
|
|
|
|
#7 | |||
|
Member
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
|
Quote:
Riguardo l'uso delle std::string adotterò anche questo consiglio. Per ora l'unico problema, come da un più vecchio topic, è la persistenza del messaggio d'errore quando la std::string và out-of-scope (con un throw). Non mi và di utilizzare librerie esterne solo per aggirare questo problema. Quote:
Quote:
Grazie ancora, mi stai aiutando ad entrare ulteriormente nell'ottica C++.
__________________
|
|||
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 21:14.




















