Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Recensione Samsung Galaxy S26+: sfida l'Ultra, ma ha senso di esistere?
Recensione Samsung Galaxy S26+: sfida l'Ultra, ma ha senso di esistere?
Equilibrio e potenza definiscono il Samsung Galaxy S26+, un flagship che sfida la variante Ultra e la fascia alta del mercato con il primo processore mobile a 2nm. Pur mantenendo l'hardware fotografico precedente, lo smartphone brilla per un display QHD+ da 6,7 pollici d'eccellenza, privo però del trattamento antiriflesso dell'Ultra, e per prestazioni molto elevate. Completano il quadro la ricarica wireless a 20W e, soprattutto, un supporto software settennale
Zeekr X e 7X provate: prezzi, autonomia fino a 615 km e ricarica in 13 minuti
Zeekr X e 7X provate: prezzi, autonomia fino a 615 km e ricarica in 13 minuti
Zeekr sbarca ufficialmente in Italia con tre modelli elettrici premium, X, 7X e 001, distribuiti da Jameel Motors su una rete di 52 punti vendita già attivi. La Zeekr X parte da 39.900 euro, la 7X da 54.100: piattaforma a 800V, chip Snapdragon di ultima generazione, ricarica ultraveloce e un'autonomia dichiarata fino a 615 km WLTP. Le prime consegne sono previste a metà aprile
Marathon: arriva il Fortnite hardcore
Marathon: arriva il Fortnite hardcore
Marathon è il titolo multiplayer competitivo del momento. Ecco quali sono le caratteristiche di gioco principali, insieme alle nostre prime considerazioni dopo qualche "run" nell'extraction shooter di Bungie
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 10-09-2010, 12:50   #1
Opcode
Member
 
L'Avatar di Opcode
 
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();
	};
e definita come segue:

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);
}
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:
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);
}
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:
Codice:
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.
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2010, 13:18   #2
tomminno
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.
tomminno è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2010, 14:17   #3
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Anzitutto grazie della risposta. Mi hai aiutato a fixare il problema.
Quote:
Originariamente inviato da tomminno Guarda i messaggi
La classe Exception non ha i metodi dichiarati come virtual.
Questo mi ha permesso di utilizzare i metodi della classe figlio, ci avevo pensato già alla virtual ma non ero sicuro di poter dichiarare un metodo virtuale e poi poterlo definire (per altro colpa mia che mi son fatto venire il dubbio, dopo averlo già fatto).
Quote:
Ma non capisco perchè mai ridichiarare _message (tra l'altro come char*) quando è già protected in Exception?
Anche qui, ti ringrazio, avevo fatto la modifica proprio per poterci lavorare ma mi ero dimenticato di usare quello. Probabilmente non devo lavorarci sopra quando sono stanco
Quote:
E ancora perchè non fai derivare Exception da std::exception?
Sinceramente?
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:
Infine non è proprio bello che un'eccezione spari fuori un messagebox.
Queste eccezioni sono per un programma con interfaccia grafica, e se qualcosa và storto bisogna mostrarlo all'utente e pensavo di farlo tramite una MessageBox, tutto qui. Si capisce che se fosse una applicazione diversa, non mi verrebbe mai in mente di usare la MessageBox. Hai qualche soluzione alternativa da proporre per fare questo?


Grazie ancora.
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2010, 14:55   #4
tomminno
Senior Member
 
Iscritto dal: Oct 2005
Messaggi: 3306
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Sinceramente?
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.
Il fatto di non dover gestire _message e what()?
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:
Queste eccezioni sono per un programma con interfaccia grafica, e se qualcosa và storto bisogna mostrarlo all'utente e pensavo di farlo tramite una MessageBox, tutto qui. Si capisce che se fosse una applicazione diversa, non mi verrebbe mai in mente di usare la MessageBox. Hai qualche soluzione alternativa da proporre per fare questo?


Grazie ancora.
Più che altro a livello di separazione delle responsabilità proprie della programmazione ad oggetti e di riusabilità del codice.
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.
tomminno è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2010, 15:29   #5
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Quote:
Originariamente inviato da tomminno Guarda i messaggi
Il fatto di non dover gestire _message e what()?
Perdona la mia ignoranza, se sbaglio correggimi, ma la classe std::exception definisce exception::what() come:
Codice:
  virtual const char* what() const throw();
Quindi dovrei comunque farne la mia implementazione, e stando alla documentazione:
Codice:
class exception {
public:
  exception () throw();
  exception (const exception&) throw();
  exception& operator= (const exception&) throw();
  virtual ~exception() throw();
  virtual const char* what() const throw();
}
Non ha un membro _message per salvare l'errore (giustamente è la base exception class), quindi la sola motivazione che mi sembra reggere è:
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:
Più che altro a livello di separazione delle responsabilità proprie della programmazione ad oggetti e di riusabilità del codice.
Se volessi utilizzare le tue classi per gestire eccezioni interne non necessariamente da mostrare all'utente?
Basterebbe catturare l'eccezione e non chiamare uno dei metodi show() o fatal()... probabilmente dovrei rendere accessibile il metodo what per ottenere l'errore in modo non intrusivo.
Quote:
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.
A questo non ci avevo pensato, ed effettivamente non hai torto, sui test che ho effettuato il popup della MessageBox ha sempre portato quest'ultima in primo piano.
Opcode è offline   Rispondi citando il messaggio o parte di esso
Old 10-09-2010, 16:46   #6
tomminno
Senior Member
 
Iscritto dal: Oct 2005
Messaggi: 3306
Quote:
Originariamente inviato da Opcode Guarda i messaggi
Perdona la mia ignoranza, se sbaglio correggimi, ma la classe std::exception definisce exception::what() come:
Codice:
  virtual const char* what() const throw();
Quindi dovrei comunque farne la mia implementazione, e stando alla documentazione:
Codice:
class exception {
public:
  exception () throw();
  exception (const exception&) throw();
  exception& operator= (const exception&) throw();
  virtual ~exception() throw();
  virtual const char* what() const throw();
}
Non ha un membro _message per salvare l'errore (giustamente è la base exception class), quindi la sola motivazione che mi sembra reggere è:
In realtà potresti riuscire a comporre il messaggio d'errore nel costruttore, io ad esempio ho costruito una classe Win32Exception che compone in un metodo statico il messaggio d'errore ricavato da FormatMessageA in modo da avere un'eccezione sollevata in caso di una chiamata Win32 fallita.
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:
Basterebbe catturare l'eccezione e non chiamare uno dei metodi show() o fatal()... probabilmente dovrei rendere accessibile il metodo what per ottenere l'errore in modo non intrusivo.
Stai legando indissolubilmente tutti gli utilizzatori della tua Exception al funzionamento interno della classe. In caso di refactoring del codice qualcosa potrebbe smettere di funzionare.

Quote:
A questo non ci avevo pensato, ed effettivamente non hai torto, sui test che ho effettuato il popup della MessageBox ha sempre portato quest'ultima in primo piano.
Ad esempio se l'utente ottiene un'eccezione che causa l'invocazione del metodo fatal, ma prima che questo venga invocato esegue altre azioni sulla GUI è molto probabile che il messagebox rimanga poi in secondo piano.
tomminno è offline   Rispondi citando il messaggio o parte di esso
Old 11-09-2010, 21:26   #7
Opcode
Member
 
L'Avatar di Opcode
 
Iscritto dal: Jun 2010
Città: Asti
Messaggi: 85
Quote:
Originariamente inviato da tomminno Guarda i messaggi
In realtà potresti riuscire a comporre il messaggio d'errore nel costruttore, io ad esempio ho costruito una classe Win32Exception che compone in un metodo statico il messaggio d'errore ricavato da FormatMessageA in modo da avere un'eccezione sollevata in caso di una chiamata Win32 fallita.
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.
Seguirò i tuoi consigli. Ho già implementato la nuova classe Exception derivando da std::exception.
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:
Stai legando indissolubilmente tutti gli utilizzatori della tua Exception al funzionamento interno della classe. In caso di refactoring del codice qualcosa potrebbe smettere di funzionare.
Non saprei come altro fare, cioè posso fare il solo metodo che restituisce sotto forma di std::string l'errore testuale, e tutte le altre informazioni utili nel contesto di gestione dell'eccezione, ma poi toccherebbe al programmatore finale, chiamare la MessageBoxA. Quello che dici non è affatto sbagliato, anzi, però potrebbe essere snervante visto che le eccezioni derivate da Exception saranno tutte da mostrare all'utente finale.
Quote:
Ad esempio se l'utente ottiene un'eccezione che causa l'invocazione del metodo fatal, ma prima che questo venga invocato esegue altre azioni sulla GUI è molto probabile che il messagebox rimanga poi in secondo piano.
Chiarissimo.

Grazie ancora, mi stai aiutando ad entrare ulteriormente nell'ottica C++.
Opcode è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Recensione Samsung Galaxy S26+: sfida l'Ultra, ma ha senso di esistere? Recensione Samsung Galaxy S26+: sfida l'Ultra, m...
Zeekr X e 7X provate: prezzi, autonomia fino a 615 km e ricarica in 13 minuti Zeekr X e 7X provate: prezzi, autonomia fino a 6...
Marathon: arriva il Fortnite hardcore Marathon: arriva il Fortnite hardcore
HP Imagine 2026: abbiamo visto HP IQ all’opera, ecco cosa può (e non può) fare HP Imagine 2026: abbiamo visto HP IQ all’opera, ...
PNY RTX 5080 Slim OC, sembra una Founders Edition ma non lo è PNY RTX 5080 Slim OC, sembra una Founders Editio...
Panasonic LUMIX TZ300: la nuova compatta...
La società aerospaziale italiana ...
Il Politecnico di Milano guiderà ...
Amazon Leo punta ad aumentare la cadenza...
Pro Type Ergo: Razer si lancia a gamba t...
Artemis II: dal guasto risolto alla toil...
Le immagini e i video più spettac...
Previsioni drastiche di TrendForce: la D...
La PS6 portatile sarà più potente della ...
Toshiba annuncia i primi dischi FC-MAMR ...
Amazon Leo offrirà l'accesso a Internet ...
Alienware presenta i nuovi desktop Area-...
Fiat 600 benzina senza ibrido: 101 CV, c...
DJI Mini 4K Combo a 269€ o DJI Neo da 14...
Addio agli sprechi nel riciclo: il Fraun...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 20:47.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v