Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Motorola edge 70: lo smartphone ultrasottile che non rinuncia a batteria e concretezza
Motorola edge 70: lo smartphone ultrasottile che non rinuncia a batteria e concretezza
Motorola edge 70 porta il concetto di smartphone ultrasottile su un terreno più concreto e accessibile: abbina uno spessore sotto i 6 mm a una batteria di capacità relativamente elevata, un display pOLED da 6,7 pollici e un comparto fotografico triplo da 50 MP. Non punta ai record di potenza, ma si configura come alternativa più pragmatica rispetto ai modelli sottili più costosi di Samsung e Apple
Display, mini PC, periferiche e networking: le novità ASUS al CES 2026
Display, mini PC, periferiche e networking: le novità ASUS al CES 2026
Sono molte le novità che ASUS ha scelto di presentare al CES 2026 di Las Vegas, partendo da una gamma di soluzioni NUC con varie opzioni di processore passando sino agli schermi gaming con tecnologia OLED. Il tutto senza dimenticare le periferiche di input della gamma ROG e le soluzioni legate alla connettività domestica
Le novità ASUS per il 2026 nel settore dei PC desktop
Le novità ASUS per il 2026 nel settore dei PC desktop
Molte le novità anticipate da ASUS per il 2026 al CES di Las Vegas: da schede madri per processori AMD Ryzen top di gamma a chassis e ventole, passando per i kit di raffreddamento all in one integrati sino a una nuova scheda video GeForce RTX 5090. In sottofondo il tema dell'intelligenza artificiale con una workstation molto potente per installazioni non in datacenter
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 10-09-2010, 13: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, 14: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, 15: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, 15: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, 16: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, 17: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, 22: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


Motorola edge 70: lo smartphone ultrasottile che non rinuncia a batteria e concretezza Motorola edge 70: lo smartphone ultrasottile che...
Display, mini PC, periferiche e networking: le novità ASUS al CES 2026 Display, mini PC, periferiche e networking: le n...
Le novità ASUS per il 2026 nel settore dei PC desktop Le novità ASUS per il 2026 nel settore de...
Le novità MSI del 2026 per i videogiocatori Le novità MSI del 2026 per i videogiocato...
I nuovi schermi QD-OLED di quinta generazione di MSI, per i gamers I nuovi schermi QD-OLED di quinta generazione di...
E-mail reset password di Instagram: la c...
La NASA ha discusso le problematiche del...
Il razzo spaziale NASA SLS e la capsula ...
Stazione Spaziale Internazionale: Crew-1...
Samsung Galaxy S26 Ultra: la ricarica de...
Apple ha un nuovo partner per la sua App...
Trenitalia introduce il prezzo dinamico ...
OnePlus non si ferma più: c'&egra...
DAZN sconta il piano Full per 6 mesi, se...
L'uso dell'IA nei giochi è cancer...
Meta punta sul nucleare USA per alimenta...
Le migliori offerte Amazon del weekend: ...
La crisi dell'hardware spinge i negozi g...
Apple Watch SE 3 scontato su Amazon: il ...
Robot aspirapolvere davvero scontati: si...
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: 01:48.


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