Twitter und Facebook-Anbindung
X
Tweet Follow @twitterapi
!!! Anbindung an twitter und facebook öffnen !!!

Wenn Ihnen mein Online-Buch gefällt,
dann bedanken Sie sich doch mit einer kleinen Spende...

26.3 Eigene Exceptionobjekte

26.3 Eigene Exceptionobjekte

Allerdings ergibt sich jetzt eine kleine Schwierigkeit. Man kann immer nur einen Datentyp zurück geben und somit ist es nicht ohne weiteres möglich, z.B. einen Fehlercode und einen Fehlertext zu werfen. Ein Lösungsansatz wäre, sich eine Struktur zu bauen, welche einen Integer und einen String aufnehmen kann, aber spätestens wenn man mehrere verschiedene Exceptions feuern will, wird diese Herangehensweise auch lästig, da man jedes mal aufs neue überlegen muss, welchen Fehlercode und welchen Text man im Einzelnen angeben muss. Gerade in sehr großen Projekten, müsste man sich erst eine Dokumentation heran ziehen oder selbst im Quelltext auf die Suche gehen. Um der ganzen Sache aus dem Weg zu gehen, ist es also klüger, sich ein universelles Ausnahmeobjekt zu bauen und dieses zu werfen. Im Konstruktor des Objektes kann man dann über eine Enumeration, den Fehlertyp wählen und die Codevervollständigung zeigt einem gleich alle Möglichkeiten an. Diese Herangehensweise ist nicht nur viel ergonomischer, sondern spart gelegentlich auch viel Zeit und Nerven.

Im folgenden Quelltext habe ich eine solche universelle Exceptionklasse definiert. Zunächst also die Header-Datei.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
					
#pragma once

// Mögliche Fehlermeldungen
#define DEF_STR_EXCEPTION_1 "Fehlersituation 1 ist eingetreten!\n"
#define DEF_STR_EXCEPTION_2 "Fehlersituation 2 ist eingetreten!\n"
#define DEF_STR_EXCEPTION_3 "Fehlersituation 3 ist eingetreten!\n"



// Universelle Exceptionklasse
class CMyException {
	public:
		// Mögliche Fehlerarten
		enum EErrorType	{	eetSituation1,
						eetSituation2,
						eetSituation3,
						eetCount,
						eetNone	};

		// Konstruktor
		CMyException(EErrorType eErrorType);

		// Gibt den Fehlercode zurück
		int		GetErrorCode();
		// Gibt den Fehlertext zurück
		const char*	GetErrorMessage();

	private:
		EErrorType		m_eType;
		static const char*	s_aMessages[];
};
					

Wie Sie in den Zeile 4 bis 6 sehen, habe ich zunächst, an einer zentralen Stelle, alle möglichen Fehlertexte zusammengefasst. Dies erleichtert später beispielsweise die Korrektur der Texte hinsichtlich Inhalt und Rechtschreibfehlern.

Ab Zeile 11 erfolgt dann die Klassendefinition. Wie Sie in den Zeilen 14 bis 18 sehen können, erstelle ich mir einen Aufzählungstyp mit drei verschiedenen Elementen. Jene Bezeichnungen sollten Sie gut durchdenken, den jene werden nach außen getragen und beim aufrufen des Konstruktors, durch die Codevervollständigung, angezeigt.

Anschließend folgen noch die Definitionen für den Konstruktor, zwei Methoden zum Holen des Fehlercodes und des Fehlertextes, sowie zweier Membervariablen. Auffällig hierbei sollte sein, dass das Attribut "s_aMessages", in Zeile 30, eine statische Klassenvariable ist. Dies ist nicht zwangsläufig notwendig, aber wie Sie gleich sehen werden, erspare ich mir damit ein wenig Code, weil ich zum einen im Konstruktor nicht extra Speicher anfordern muss und somit auch keinen Destruktor benötige, um den Speicher wieder freizugeben.

Nachfolgend sehen Sie nun die Implementierung der drei Methoden in der zugehörigen CPP Datei.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
					
#include "MyException.h"

// Statische Klassenvariable initialisieren
const char* CMyException::s_aMessages[]	= {	DEF_STR_EXCEPTION_1,
						DEF_STR_EXCEPTION_2,
						DEF_STR_EXCEPTION_3};

// Konstruktor ////////////////////////////////////////////////////////////////
CMyException::CMyException(EErrorType eErrorType) { 
	m_eType = eErrorType;
} // CMyException /////////////////////////////////////////////////////////////



// Gibt den Fehlercode zurück /////////////////////////////////////////////////
int CMyException::GetErrorCode() {
	return (int)m_eType;
} // GetErrorCode /////////////////////////////////////////////////////////////



// Gibt den Fehlertext zurück /////////////////////////////////////////////////
const char* CMyException::GetErrorMessage() {
	return s_aMessages[m_eType];
} // GetErrorMessage //////////////////////////////////////////////////////////
					

Da ich an dieser Stelle davon ausgehe, dass Sie das Klassenkonzept und Arrays soweit verstanden haben, spare ich mir an dieser Stelle die Erklärung zum Quelltext, zumal nichts spannendes passiert. Gleiches gilt für die Implementierung in der "main". Der Vollständigkeit halber, sehen Sie nachstehend trotzdem ein kleines Beispiel.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
					
#include <stdio.h>
#include "MyException.h"



// Wirft ein Exceptionobjekt //////////////////////////////////////////////////
void Test() {
	throw CMyException(CMyException::eSituation1);
} // Test /////////////////////////////////////////////////////////////////////

// ...

try {
	Test();		
} catch (CMyException oException) {
	printf("Fehler (%i): %s\n",	oException.GetErrorCode(),
					oException.GetErrorMessage());
} // end of try
					

Ausgabe:

Fehler (0): Fehlersituation 1 ist eingetreten!
		

Interessant ist hier lediglich die Zeile 8. Der Aufruf des Konstruktors "CMyException", erzeugt ein statisches Objekt mir den gewünschten Fehlerinformationen und genau jenes wird gefeuert und im "catch" Block aufgefangen und ausgewertet. Dies ist soweit unkritisch und erzeugt keinerlei Speicherlecks, da das Objekt statisch erzeugt wurde. Sie brauchen/dürfen es also nicht im "catch" Block freigeben.

Zum Seitenanfang
Zum Inhaltsverzeichnis

© Copyright by Thomas Weiß, 2009 - 2012